Java wait () и notify () для полей суперкласса [дубликат]

Если во время проверки не появляется ошибка MySQL, убедитесь, что вы правильно создали таблицу базы данных. Это случилось со мной. Ищите любые нежелательные запятые или цитаты.

28
задан Raphael Ahrens 4 November 2015 в 17:10
поделиться

4 ответа

Я не могу понять причину, по которой мы должны «никогда не синхронизироваться в Boolean»

Вам нужно synchronize на экземпляр объекта константы . Если вы синхронизированы на любом объекте, который вы назначаете (т. Е. Меняете объект), то объект не является постоянным, а разные потоки будут синхронизироваться на разных объектах экземплярах . Поскольку они синхронизируются в разных объектных экземплярах, в этот же момент одновременно будут входить защищенные блоки, и условия гонки будут происходить. Это тот же самый ответ для синхронизации на Long, Integer и т. Д.

Boolean isOn;
...
synchronized (isOn) {
   if (isOn) {
      // this changes the synchronized object isOn to another object
      // so another thread can then enter the synchronized with this thread
      isOn = false;

Чтобы усугубить ситуацию (как отметил в своем ответе @McDowell) любой Boolean, который создается через autoboxing (isOn = true) - это тот же объект, что и Boolean.TRUE (или .FALSE), который является одиночным элементом в ClassLoader через всех объектов . Ваш объект блокировки должен быть локальным для класса, в котором он используется, иначе вы будете блокировать один и тот же одноэлементный объект, который другие классы могут блокировать в других случаях блокировки, если они совершают ту же ошибку.

правильный шаблон, если вам нужно заблокировать логическое значение, это определить объект блокировки private final:

private final Object lock = new Object();
...

synchronized (lock) {
   ...

Или вы также должны рассмотреть возможность использования объекта AtomicBoolean, что означает, что вам может не потребоваться synchronize на нем вообще.

private final AtomicBoolean isOn = new AtomicBoolean(false);
...

// if it is set to false then set it to true, no synchronization needed
if (isOn.compareAndSet(false, true)) {
    statusMessage = "I'm now on";
} else {
    // it was already on
    statusMessage = "I'm already on";
}

В вашем случае, поскольку вам кажется, что вам нужно переключать его вкл / выкл с помощью потоков, вам все равно нужно synchronize на объекте lock и задайте логическое значение и избегайте условия проверки / установки гонки:

synchronized (lock) {
    if (isOn) {
        isOn = false;
        statusMessage = "I'm off";
        // Do everything else to turn the thing off
    } else {
        isOn = true;
        statusMessage = "I'm on";
        // Do everything else to turn the thing on
    }
}

Наконец, если вы ожидаете, что statusMessage будет доступен из других потоков, тогда он должен быть отмечен как volatile, если вы не будете synchronize во время получения.

54
ответ дан Gray 28 August 2018 в 04:35
поделиться
private Boolean isOn = false;
public void doSomeStuffAndToggleTheThing(){
   synchronized(isOn){

Это ужасная идея. isOn будет ссылаться на тот же объект, что и Boolean.FALSE, который является общедоступным. Если какой-либо другой фрагмент плохо написанного кода также решает заблокировать этот объект, две совершенно несвязанные транзакции должны будут ждать друг друга.

Замки выполняются на экземплярах объекта , а не на переменные, которые ссылаются на них:

enter image description here [/g1]

16
ответ дан McDowell 28 August 2018 в 04:35
поделиться
0
ответ дан Raffaele 28 August 2018 в 04:35
поделиться

Изменить: ответ Серый правильный.

Что я хочу добавить: ваш архитектор прав, если с точки зрения Boolean неизменен, зачем его синхронизировать? Но многопоточность сложна и основана на сценарии.

-3
ответ дан 卢声远 Shengyuan Lu 28 August 2018 в 04:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: