2015-11-17 3 views
2
public class MyLockConditionTest { 
    private final Lock alock = new ReentrantLock(); 
    private final Condition condition = alock.newCondition(); 
    private String message = null; 

    public void waitForCallback() { 
     alock.lock(); 
     try { 
      // wait for callback from a remote server 
      condition.await(); 
      doSomething(message); 
     } finally { 
       alock.unlock(); 
     } 
    } 

    // another thread will call this method as a callback to wake up the thread called condition.await() 
    public void onCallbackReceived(String message) { 
     alock.lock(); 
     try { 
      this.message = message 
      condition.signal(); 
     } finally { 
       alock.unlock(); 
     } 
    } 
} 

У меня есть этот код с использованием ReentrantLock и Condition для реализации класса, который будет ждать определенных обратных вызовов с удаленного сервера. Я тестировал этот код и, кажется, работаю, но у меня есть несколько вопросов.Состояние замка Reentrance

  1. Зачем мне нужно делать alock.lock()/unlock() в onCallbackReceived(). Без вызова lock()/unlock() я получал исключение IllegalState. Я запутался, потому что блокировка удерживается вызывающим объектом waitForCallback(), когда onCallbackReceived() вызывается другим потоком, так что alock.lock() в onCallbackReceived() всегда терпит неудачу.

  2. Нужно ли обертывать условие.await() в waitForCallback() с циклом while?

    в то время как (сообщение == null) состояние.await();

+0

1) В ожидании состояния требуется мьютекс, чтобы защитить состояние от изменения небезопасными способами (видимость). 2) ложные пробуждения среди других, также https://computing.llnl.gov/tutorials/pthreads/#ConVarSignal для того же самого на низком уровне – zapl

ответ

1

Почему мне нужно сделать alock.lock()/разблокировки() в onCallbackReceived(). Без вызова lock()/unlock() я получал исключение IllegalState.

Вы пытаетесь установить signal состояние, в котором вы не являетесь владельцем замка. Единственный способ удерживать замок - если onCallbackReceived вызывается из doSomething, в котором нет указаний, которые происходят.

Нужно ли обертывать условие.await() в waitForCallback() с циклом while?

Да, представьте, что у вас есть 5 потоков, остановленных при условии, и 5 потоков заблокированы на lock. Только один поток может проснуться. Что, если, когда ожидающая нить наконец просыпается, в другом потоке было пустое поле? Вам нужно будет снова проверить, чтобы предикат по-прежнему оставался верным.

+0

Спасибо за ваш комментарий. onCallbackReceived не вызывается из doSomething doSeomthing. Есть еще один поток, ссылающийся на этот объект класса, и поток вызывает onCallbackReceived, и этого я не понимаю. блокировка удерживается вызывающим устройством waitForCallback, но onCallbackReceived все еще может получить блокировку и иметь возможность достигнуть сигнала() – codereviewanskquestions

+0

Итак, вы говорите, что оба потока одновременно удерживают «блокировку»? –

+0

authCallbackLock.isLocked() и authCallbackLock.isHeldByCurrentThread() дают мне «false» в onCallbackReceived() прямо перед alock.lock(), хотя authCallbackLock.isLocked() является истинным после того, как alock.lock() в waitForCallback() – codereviewanskquestions

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