AtomicBoolean, где замок?
AtomicBoolean использует собственный код для синхронизации. Как это переводится в Java-замки?
В чем разница между:
AtomicBoolean a = new AtomicBoolean();
synchronized (a) {
a.set(true);
}
против:
a.set(true)
Я знаю, что synchronized(a) не нужен, потому что сам по себе будет гарантировать, что операция является атомарной. Но является ли блокировка в synchronized(a) такой же блокировкой, как в a.set(true)?
4 ответа
В некоторых случаях атомарность зависит от JVM, например, от set / get, но в других случаях полагается на класс sun.misc.Unsafe. Вы можете проверить код по адресу:
Также стоит посмотреть на:
который используется для многих вещей в JDK, хотя, к сожалению, это не публичный класс. Сделано более грустным, потому что его так явно называют, что он может быть публичным и полностью "безопасным" для использования;-)
Я должен добавить, что вся идея атомарных классов состоит в том, чтобы избежать блокировок и синхронизации, которые часто улучшают производительность. Вам не нужно использовать блокировки для их защиты, но вы можете полагаться на такие операции, как CompareAndSwap или incrementAndGet (для чисел), которые не являются стандартными при использовании блокировки.
Нет. AtomicBoolean
фактически, все атомарные классы используют сравнение и обмен, чтобы гарантировать атомарность.
Ключевое слово синхронизации обеспечивает три гарантии в соответствии с JMM. 1. Атомность 2. Видимость 3. Изменение порядка
но синхронизация в природе блокирует.
Все атомные классы в Java, такие как AtomicInteger, AtomicLong, AtomicBoolean и т. Д., Также предоставляют три вышеуказанные гарантии. Но они не блокируют другие темы.
Они обеспечивают 1. атомарность - с помощью операции CompareAndSwap. 2. Видимость и изменение порядка - они обеспечиваются объявлением базовой переменной как изменчивой.
например, в AtomicInteger базовая переменная int объявлена как volatile
private volatile int value;
Этот:
a.set(true);
внутренне не синхронизируется, взгляните на код AtomicBoolean.java в JDK 1.7 (из src.zip):
/**
* Unconditionally sets to the given value.
*
* @param newValue the new value
*/
public final void set(boolean newValue) {
value = newValue ? 1 : 0;
}
так что да, это отличается от синхронизированной версии