2014-01-06 2 views
2

В настоящее время я читаю раздел о параллелизме в книге «Хорошо обоснованная Java-разработчик», и этот пример кода, демонстрирующий параллельность блоков, должен заходить в тупик, но, насколько я вижу, это не так. Вот код:Где тупик в этом примере?

public class MicroBlogNode implements SimpleMicroBlogNode { 

    private final String ident; 

    public MicroBlogNode(String ident_){ 
     ident = ident_; 
    } 

    public String getIdent(){ 
     return ident; 
    } 

    public static Update getUpdate(String _name){ 
     return new Update(_name); 
    } 

    public synchronized void propagateUpdate(Update upd_, MicroBlogNode backup_){ 
     System.out.println(ident + ": received: " + upd_.getUpdateText() + " ; backup: " + backup_.getIdent()); 
     backup_.confirmUpdate(this, upd_); 
    } 

    public synchronized void confirmUpdate(MicroBlogNode other_, Update update_){ 
     System.out.println(ident + ": received confirm: " + update_.getUpdateText() + " from " + other_.getIdent() + "\n"); 
    } 

    public static void main(String[] args) { 
     final MicroBlogNode local = new MicroBlogNode("localhost"); 
     final MicroBlogNode other = new MicroBlogNode("remotehost"); 
     final Update first = getUpdate("1"); 
     final Update second = getUpdate("2"); 

     new Thread(new Runnable() { 
      public void run() { 
       local.propagateUpdate(first, other); 
      } 
     }).start(); 

     new Thread(new Runnable() { 
      public void run() { 
       other.propagateUpdate(second, local); 
      } 
     }).start(); 
    } 
} 

Когда я запускаю его я получаю следующий вывод:

localhost: received: 1 ; backup: remotehost 
remotehost: received confirm: 1 from localhost 

remotehost: received: 2 ; backup: localhost 
localhost: received confirm: 2 from remotehost 

В книге говорится, что если вы запустите код, вы обычно видите пример тупиковой ситуации, как потоки будут сообщать о получении обновления, но ни один из них не подтвердит получение обновления для , который является резервным потоком. Причина этого в том, что каждый поток требует, чтобы другой освободил блокировку, которую он удерживает, прежде чем способ подтверждения может прогрессировать.

Насколько я вижу, это не так - каждый поток подтверждает получение обновления, для которого они являются резервным потоком.

Заранее спасибо.

+3

Вы уверены, что это пример из книги? Покажите нам класс «Обновить». –

+0

Где находится метод getUpdateText? – wheaties

ответ

1

Тупик происходит, когда у вас есть local, вызывающий операцию с резьбой по confirmUpdate, когда other пытается сделать тот же звонок. Таким образом, тупиковые происходит после этого порядка операций

  1. Local себя замки, вызвав propagateUpdate в связи с заявлением, что он является synchronized (см Synchronized Member Function in Java)
  2. «Other» самих замков по телефону propagateUpdate
  3. Local попытки чтобы получить блокировку на Other, чтобы позвонить по телефону confirmUpdate, но не может с Other уже заблокирован в другой теме.
  4. Other пытается сделать то же самое и не удается по той же причине.

Если это действительно работает, возможно, это происходит потому, что это происходит так быстро. Запустите его еще несколько раз. Тема вопроса никогда не работает, когда вы хотите, чтобы они работали.

+0

Повторное выполнение нескольких операций, и мне удалось заблокировать код. – user283188

+0

@ user283188 Отлично! Это классическая проблема «голодания», в которой один поток пытается использовать ресурс, который в настоящее время использует другой поток, но не имеет возможности отказаться. – wheaties

2

Это похоже на время. На вашем выходе показано, что поток localhost завершился до запуска пула remotehost (other).

Попробуйте положить Thread.sleep (1000) в методе propogateUpdate после System.out

public synchronized void propagateUpdate(Update upd_, MicroBlogNode backup_){ 
    System.out.println(ident + ": received: " + upd_.getUpdateText() + " ; backup: " + backup_.getIdent()); 
    Thread.sleep(1000); 
    backup_.confirmUpdate(this, upd_); 
} 

Это должно заставить затор.

Смежные вопросы