2015-04-26 3 views
0

У меня проблема, с которой я застрял несколько часов, и я действительно не знаю, как ее решить. Это довольно просто - у меня есть потоки, один из них должен ждать сигнала от другого. Так или иначе, даже если я делаю сигнал при условии ... ничего не происходит! Похоже, что нить все еще спит. Это действительно странно, проблема, но это может быть моя вина, что я не понимаю, что-то хорошо ...Java, Lock, Condition - Signal not waking waiting thread

Вот часть моего кода:

@Override 
public void bodyProduced() { 
    lock.lock(); 
    producedBodies++; 
    if (producedEngines == 0) { 
     while(producedEngines==0) 
     { 
      System.out.println("I am still waiting!"); 
      body.awaitUninterruptibly(); 
     } 
     System.out.println("I waked up!"); 
     producedBodies--; 
     producedEngines--; 
    } else { 
     engine.signalAll(); 
    } 
} 

Я уверен, что body.signalAll(); вызывается, когда в этом состоянии присутствуют потоки - я проверил, и отладчик много раз перебирает эту строку. Тем не менее, строка «Я жду» появляется только один раз за трэд, а «я просыпаюсь» никогда ...

Любые идеи, как исправить, или что проверить? Я попробовал почти все ...

Спасибо за ваше время и помощь!

ответ

2

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

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

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

в вашем случае, я рекомендую, учитывая использование Synchronized, CountDownLatch или, возможно, ExecutorServices? (Вы на самом деле не описали проблему, которая у вас есть). Если ни одна из функций, прилагаемых к JDK, не работает для вас, пожалуйста, также взгляните на Heinz Kabutz's java newsletter, потому что этот парень знает, как работать с параллелизмом.

+0

Спасибо за ваш ответ. Я знаю об изменчивой вещи, и я использую ее здесь. Так что это не проблема. Ну, это часть моей учебной задачи, поэтому я вынужден использовать блокировку/состояние здесь. Похоже, проблема в том, что я должен сначала разблокировать, и только после того, как я разблокирую другой поток, будет просыпаться. Довольно странно, потому что я не хочу, чтобы часть после пробуждения была синхронизирована. –

2

Когда вы используете ReentrantLock, вы должны вызвать unlock() после критического раздела. Это должно быть сделано в наконец пункте

lock.lock(); 
try{ 
// critical section code (may throw exception) 
} finally { 
    lock.unlock(); 
} 

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

+0

Я знаю об этом, но в моем случае блокировка разблокирована другим способом. То, что я хотел бы достичь, это: 1. Thread находится в критическом разделе. 2. Он просыпается еще один поток, Waked thread уже находится за пределами его критической секции, но сначала он все еще продолжает делать синхронизированные вещи. –

+0

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