Условие общего доступа Java между классами создает IllegalMonitorStateException: null

У меня есть структура примерно так:
Lock wrapper - используется для хранения блокировки, состояния и объекта из ответа

public class LockWrapper{
    private Lock lock;
    private Condition myCondition;
    private MyObject myObject;

    public LockWrapper(Lock lock, Condition myCondition) {
        this.lock = lock;
        this.myCondition = myCondition;
    }

    public Condition getMyCondition() {
        return myCondition;
    }

    public MyObject getMyObject() {
        return myObject;
    }

    public void setObject(MyObject myObject) {
        this.myObject = myObject;
    }

    public Lock getLock() {
        return lock;
    }

}

Задача - помещается в пул потоков для выполнения. Он инициирует запросы к серверу, а затем ожидает ответа сервера.

public class MyTask implements Runnable{
    private Lock lock = new ReentrantLock();
    private Condition myCondition = lock.newCondition();
    private MyWebSocketAPI api;

    public MyTask(MyWebSocketAPI api) {
         this.api = api;
    }

    @Override
    public void run() {
         lock.lock();
         try {
              // long randomLong = generateRandomLong();
              api.sendRequest(randomLong, new LockWrapper(lock, myCondition));
              myCondition.await();
              //do something after we got a response
         } finally{
              lock.unlock();
         }
    }

}

WebSocket - получает запросы и уведомляет задачи об ответах

 public abstract class MyWebSocketAPI extends WebSocketClient {
    //...
    private Map<Long, LockWrapper> lockWrappers = new ConcurrentHashMap<>();

    public void sendRequest(Long id, LockWrapper lockWrapper){
        this.lockWrappers.put(id, lockWrapper);
        //processRequest
    }

    @Override
    public void onMessage(String message) {
        LockWrapper lockWrapper = lockWrappers.get(message.get(0).getAsLong());

        lockWrapper.getLock().lock();
        try{
            lockWrapper.setMyObject(new MyObject(message));
            this.lockWrappers.put(message.get(0).getAsLong(), lockWrapper);
            lockWrapper.getMyCondition().signalAll();
        } finally {
            lockWrapper.getLock().unlock();
        }
    }

    //...
 }

Линия lockWrapper.getMyCondition().signalAll(); выдает исключение:

java.lang.IllegalMonitorStateException: null
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.signalAll(AbstractQueuedSynchronizer.java:1954)

Почему мои условия выдают это исключение, когда я пытаюсь уведомить задачи, что мы получили их объекты? Я где-то допустил ошибку или Java не позволяет использовать общие условия?

1 ответ

Решение

Это была моя ошибка в Task, Проблема заключалась в том, что я создавал Lock и Condition как глобальные, так и локальные при запуске метода. Замок и состояние имели одно и то же имя. В некоторых случаях я использовал lock а в некоторых случаях this.lock (Но это были два разных замка). В результате в методе onMessage У меня были Состояние и Замок, которые не были связаны друг с другом. После удаления дубликатов все работает.

Другие вопросы по тегам