Если во время проверки не появляется ошибка MySQL, убедитесь, что вы правильно создали таблицу базы данных. Это случилось со мной. Ищите любые нежелательные запятые или цитаты.
Я не могу понять причину, по которой мы должны «никогда не синхронизироваться в Boolean»
blockquote>Вам нужно
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
во время получения.
private Boolean isOn = false;
public void doSomeStuffAndToggleTheThing(){
synchronized(isOn){
Это ужасная идея. isOn
будет ссылаться на тот же объект, что и Boolean.FALSE
, который является общедоступным. Если какой-либо другой фрагмент плохо написанного кода также решает заблокировать этот объект, две совершенно несвязанные транзакции должны будут ждать друг друга.
Замки выполняются на экземплярах объекта , а не на переменные, которые ссылаются на них:
[/g1]
Изменить: ответ Серый правильный.
Что я хочу добавить: ваш архитектор прав, если с точки зрения Boolean
неизменен, зачем его синхронизировать? Но многопоточность сложна и основана на сценарии.