Возможно ли такое состояние гонки в ожидании потока, чтобы завершить задачу? - PullRequest
2 голосов
/ 08 сентября 2011

Моя неопытность с параллелизмом совершенно ясна, и я ищу здесь некоторую помощь.

Я писал многопоточное приложение на Java, пока меня одолевали сомнения. Пожалуйста, посмотрите на этот пример кода (смешивание псевдокода и Java):

Тело 1 тела (порция) :

/* It creates and starts thread Thread 2 */
if (!thread2.taskCompleted)
   thread2.wait();
/* continue execution... */

Тело 2 тела :

class Thread2 extends Thread {

    volatile boolean taskCompleted = false;

    public void run() {
        /* It executes a complex task... */
        taskCompleted = true;
        notifyAll(); // notify waiting threads
    }

}

Моя проблема проста: что произойдет, если операторы будут выполнены в таком порядке:

  1. Тема 1 запускается Тема 2
  2. Нить 2 делает что-то, но не выполняет задачу
  3. Тема 1 читает задание завершено как ложное
  4. Поток 2 завершает задачу, поднимает флаг taskCompleted и уведомляет (никого)
  5. Тема 1 начинает ждать. И никогда не кончается.

Пожалуйста, дайте мне знать, если у вас есть какие-либо идеи и / или это хорошо известный сценарий (точный дубликат?)

Ответы [ 3 ]

2 голосов
/ 08 сентября 2011

Использование флагов taskCompleted и wait()/nofiyAll() должно быть защищено блокировкой во избежание описанного вами сценария.

/* It creates and starts thread Thread 2 */
synchronized (thread2) {
  if (!thread2.taskCompleted)
    thread2.wait();
}
/* continue execution... */

и

class Thread2 extends Thread {

  boolean taskCompleted = false;

  public void run() {
    /* It executes a complex task... */
    synchronized (this) {
      taskCompleted = true;
      notifyAll(); // notify waiting threads
    }
  }
}
2 голосов
/ 08 сентября 2011

Я думаю, что эти блоки должны быть синхронизированы, см. http://download.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html.

Или вы можете использовать что-то вроде CountDownLatch, см .: http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/CountDownLatch.html

1 голос
/ 08 сентября 2011

В дополнение к тому, что другие ответили ранее, из моего личного опыта избегайте как можно больше (если вы не создаете собственные синхронизаторы), используя wait, notify и т. Д. Существует много хороших и достаточных классов, таких как семафоры, барьеры, защелки, блокировки или вообще синхронизировано. Их в 90% случаев достаточно. В приведенном выше случае вы можете использовать synchonized (this) или с любой другой переменной. Или может использовать ReenterantLock

...