IllegalMonitorStateException

Что может привести к тому, что я получаю IllegalMonitorStateException в этом коде

synchronized(syncCount){
    syncCount--;
    syncCount.notify();
}

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

Ответы

Ответ 1

Тип Integer или аналогичный? -- заменяет неизменяемый объект Integer на другой. Поэтому вы вызываете notify на другой объект, чем synchronized.

Ваш код эквивалентен:

Integer syncConunt = Integer.valueOf(5);
[...]
synchronized (syncCount) {
    syncCount = Integer.valueOf(syncCount.intValue() + 1);
    syncCount.notify();
}

Ты не одинок. Еще до J2SE 5.0 я видел пример кода, опубликованного в книге, которая назначила ссылку в синхронизированном блоке. В общем, рекомендуется отметить поля блокировки final.

Еще один важный момент - синхронизация кода на объекте, который он не "владеет". Integer объекты разделяются (Integer.valueOf(int) будет возвращать точно тот же экземпляр, если он вызван со значениями между -128 и 127 и, возможно, дополнительно). Если бы это было сделано двумя частями несвязанного кода, тогда были бы скрытые взаимодействия. Это относится к любому типу, в котором экземпляры разделяются между несвязанным кодом. Общие примеры: Integer, String, Class (используется статически синхронизированными методами) и Thread (в реализации Sun Thread используется как блокировка для join).