В этой статье мы разберём, как работают AtomicInteger, AtomicLong и остальные подобные классы из пакета java.util.concurrent.atomic в Java.
Я уже частично описал их работу, здесь же будет более подробное описание, на сколько у меня получится.
На самом деле, в этих классов гораздо больше методов, чем просто get, set и compareAndSet.
Сами эти классы наследуются от java.lang.Number, а значит, они наследуют и реализуют все его методы byteValue, shortValue, intValue, longValue, floatValue, doubleValue. Однако нам интересны не они, а методы, специфичные для атомарных классов вроде AtomicInteger:
1 |
int addAndGet(int delta) |
Атомарное увеличение значения на delta. Возвращает обновлённое значение.
1 |
boolean compareAndSet(int expect, int update) |
Сравнивает текущее значение с expect. Если они равны, то сохраняет update и возвращает true. В противном случае возвращает false.
1 |
int decrementAndGet() |
Атомарно уменьшает хранящееся значение на единицу. Возвращает новое значение.
1 |
int get() |
Возвращает текущее хранящееся значение.
1 |
int getAndAdd(int delta) |
Атомарно добавляет delta к текущему значению. Возвращает предыдущее значение.
1 |
int getAndDecrement() |
Атомарно уменьшает хранящееся значение на единицу. Возвращает предыдущее значение.
1 |
int getAndIncrement() |
Атомарно увеличивает хранящееся значение на единицу. Возвращает предыдущее значение.
1 |
int getAndSet(int newValue) |
Атомарно устанавливает новое значение и возвращает старое значение.
1 |
int incrementAndGet() |
Атомарно увеличивает хранящееся значение на единицу и возвращает новое значение.
1 |
void lazySet(int newValue) |
Устанавливает новое значение спустя какое-то время. Это новое значение может быть невидимо для других потоков какое-то время, они будут считывать старое значение. Метод может быть полезен для оптимизации производительности, так как последующие обращения к значению вполне могут получить старое значение из кэша процессора без обращения к реальному значению в памяти.
1 |
void set(int newValue) |
Устанавливает новое значение.
1 |
boolean weakCompareAndSet(int expect, int update) |
Аналогично compareAndSet, но может вернуть false и не обновить значение, даже если хранящееся значение равно expected.
Для AtomicLong методы аналогичны, но принимают и возвращают long вместо int.
Работа методов классов AtomicInteger и AtomicLong основана на специальной команде процессора CAS (compare-and-set), которая сначала сравнивает значение с ожидаемым и лишь потом заменяет его на новое.
Имейте в виду, что у нас нет специальных атомарных классов для byte, short, float и double!