И вопрос: а можно ли так делать?
Насколько я понимаю, в джаве элементы enum'а — это объекты этого самого enum'а.
А переменная типа enum — это просто ссылка на объект.
Соответственно, когда мы делаем state.wait() — мы ждем на мониторе одного объекта,
а когда делаем
state = State.STATE3;
state.notifyAll();
— то это уже нотификация на мониторе другого объекта.
Правильно ли я понимаю ситуацию? И если да, то как правильно синхронизироваться на мониторе enum'а?
Через класс-обертку?
Нельзя
F2>Насколько я понимаю, в джаве элементы enum'а — это объекты этого самого enum'а. F2>А переменная типа enum — это просто ссылка на объект. F2>Соответственно, когда мы делаем state.wait() — мы ждем на мониторе одного объекта,
F2> — то это уже нотификация на мониторе другого объекта.
Только Ява тебе такое в ранйтайме сделать не даст.
public static void main(String[] args) {
Object b1 = new Object();
Object b2 = new Object();
Object b = b1;
synchronized (b) {
b = b2;
b.notify(); // IllegalMonitorStateException
}
}
F2>Правильно ли я понимаю ситуацию? И если да, то как правильно синхронизироваться на мониторе enum'а? F2>Через класс-обертку?
Простой способ:
synchronized (State.class) {
...
}
Правильный способ:
private volatile State state;
private final Object stateLock = new Object(); // синхронизироваться на этом объекте
Простой способ не является рекомендованным, потому что локи предпочтительно делать невидимыми для остальных, тогда как объект класса (даже если сам класс private) может утечь вовне. Предосторожность тут, конечно, на 99.9999% избыточная, но если есть возможность сделать правильно, почему бы и нет.
Здравствуйте, f95.2, Вы писали:
F2>И вопрос: а можно ли так делать?
Кто-то должен атомарность обеспечивать. Причем процессору тоже нужно сказать, что доступ к этой переменной атомарен. А то на многоядерной машинке все будет очень странно работать.
Здравствуйте, Pzz, Вы писали:
Pzz> F2>И вопрос: а можно ли так делать? Pzz> Кто-то должен атомарность обеспечивать.
Спека Java Memory Model обеспечивает. Но это к вопросу не относится, bzig по делу ответил.
Здравствуйте, ·, Вы писали:
Pzz>> F2>И вопрос: а можно ли так делать? Pzz>> Кто-то должен атомарность обеспечивать. ·>Спека Java Memory Model обеспечивает. Но это к вопросу не относится, bzig по делу ответил.
И что, на каждое обращение к памяти ява вставляет инструкции процессора, обеспечивающие синхронизацию кешей? Что-то слабо верится...
Здравствуйте, Pzz, Вы писали:
Pzz> ·>Спека Java Memory Model обеспечивает. Но это к вопросу не относится, bzig по делу ответил. Pzz> И что, на каждое обращение к памяти ява вставляет инструкции процессора, обеспечивающие синхронизацию кешей? Что-то слабо верится...
Я не совсем понимаю про что ты. Атомарность это либо всё, либо ничего. Т.е. когда пишется значение, то читается либо старое целиком, либо новое целиком. А не так, чтобы первые 32 бита ещё старые, а вторые 32 бита уже новые.
Кеши и гарантия видимости значений между потоками это про другое, ты наверное happens-before имел в виду. У него в коде synchronized для этого.
Здравствуйте, f95.2, Вы писали:
F2>И поле этого типа: F2>
F2>private volatile State state;
F2>
F2>Я работаю с ним в нескольких потоках. F2>Где-то просто читаю: F2>
F2>if (state == State.STATE2) {
F2> ...
F2>}
F2>
К тому, что уже было сказано я бы только добавил, что раз уж synchronized все равно используется, что я бы убрал volatile и читал бы тоже в synchronized. Если конечно нет каких-то причин использовать именно volatile.
Здравствуйте, Pzz, Вы писали:
Pzz>И что, на каждое обращение к памяти ява вставляет инструкции процессора, обеспечивающие синхронизацию кешей? Что-то слабо верится...
Не на каждое, а там, где synchronized заканчивается.