Перейти к содержимому

Atomicinteger java что это

  • автор:

Что такое атомарность в java? [дубликат]

Понимаю, что такое атомарные операции — это неделимые операции, которые могут использоваться в многопоточном режиме без синхронизации. Например метод compareAndSet из java.util.concurrent.atomic пакета. Но не понятно, что такое атомарность? Если атомарность — это неделимость, то приведите пример пожалуйста, чтобы стало понятно данное понятие в Java.

Отслеживать
задан 3 фев 2020 в 9:43
Алексей Осецкий Алексей Осецкий
824 7 7 серебряных знаков 20 20 бронзовых знаков
посмотрите ответ по этой ссылке ru.stackoverflow.com/questions/616278/…
3 фев 2020 в 10:05

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Необходимость координации межпроцессного взаимодействия возникает из-за того, что некоторая область памяти является общей.

Мы также знаем, что все потоки процесса используют одни и те же данные:

Простой пример общей переменной x управляют два потока: A и B :

A1. x = 5 A2. print x 
B1. x = 7 

Это недетерминированный код.

Здесь нет механизма координации, поэтому мы не можем сказать, в каком порядке будут происходить эти заявления.

Некоторые возможные результаты:

5 распечатывается и является окончательным значением; 7 распечатывается и является окончательным значением; или же 5 распечатывается, а 7 является окончательным значением. 

Обратите внимание, что мы не можем распечатать 7 и получить окончательное значение 5.

Нам даже не нужно иметь несколько потоков, чтобы иметь проблему с параллелизмом. Достаточно иметь прерывания в системе. Рассмотрим приложение, которое используется для подсчета наступления какого-либо события.

Мы будем хранить количество в переменной count.

Мы предоставим пользователю возможность сброса счетчика (кнопка сброса).

Каждый раз, когда мы обнаруживаем событие, мы увеличиваем count с оператором count++; , который выглядит как один отдельный оператор.

count++; разбит на ряд более мелких операций. Если count равно 4, и мы увеличиваем его:

  1. Читаем текущее значение count (read 4)
  2. Добавляем 1 (теперь 5)
  3. Изменяем значение в памяти (write 5)

Теперь представьте, что прерывание происходит в самый неподходящий момент. Прерывание генерируется кнопкой сброса: предполагается, что значение счетчика установлено в ноль.

  1. Читаем текущее значение count (read 4)
  2. Добавляем 1 (теперь 5)
  3. INTERRUPT (обработчик прерывания)
  4. Изменяем значение в памяти (write 0)
  5. END INTERRUPT (возврат управления)
  6. Изменяем значение в памяти (write 5)

Переменная count равна 5, но она должна быть 0 (или 1). Пользователь нажал кнопку сброса, но счет не был сброшен!

Если прерывание сброса произошло до чтения переменной -> 1.

Если прерывание сброса произошло после записи переменной -> 0.

Действие сброса «потеряно».

Эта проблема возникает из-за того, что инструкция count++ на самом деле состоит из трех вещей (чтение, добавление, запись) и может быть прервана в любой момент.

Когда мы выполняем операцию, которая не может быть прервана, мы говорим, что она atomic : атомарная.

Т.е. мы хотим для определенных операций жестко установить последовательность их выполнения = атомарность.

Наиболее часто используемые атомные классы переменных в Java — AtomicInteger, AtomicLong, AtomicBoolean и AtomicReference. Эти классы представляют собой int, long, boolean и объектную ссылку соответственно, которые могут быть атомически обновлены. Основными методами, открываемыми этими классами, являются:

  • get() — получает значение из памяти, чтобы были видны изменения, внесенные другими потоками; эквивалентно чтению переменной volatile
  • set() — записывает значение в память так, чтобы изменение было видно другим потокам; эквивалентно записи переменной volatile
  • lazySet() — в конце концов записывает значение в память, может быть переупорядочено с последующими соответствующими операциями с памятью. Один из вариантов использования — обнуление ссылок, ради сбора мусора, который больше никогда не будет доступен.
  • compareAndSet() — возвращает true при успешном выполнении, в противном случае false
  • weakCompareAndSet() — Атомные классы также поддерживают метод weakCompareAndSet, который имеет ограниченную применимость. Атомно устанавливает значение для данного обновленного значения, если текущее значение совпадает с ожидаемым значением.

Потоково безопасный пример со счетчиком AtomicInteger:

public class SafeCounterWithoutLock < private final AtomicInteger counter = new AtomicInteger(0); public int getValue() < return counter.get(); >public void increment() < while(true) < int existingValue = getValue(); int newValue = existingValue + 1; if(counter.compareAndSet(existingValue, newValue)) < return; >> > > 

AtomicInteger в Java

Сегодня мы рассмотрим AtomicInteger в Java. Атомарные операции выполняются в одном блоке задачи без вмешательства других операций. Атомарные операции необходимы в многопоточной среде, чтобы избежать несогласованности данных.

AtomicInteger

package com.journaldev.concurrency; public class JavaAtomic < public static void main(String[] args) throws InterruptedException < ProcessingThread pt = new ProcessingThread(); Thread t1 = new Thread(pt, "t1"); t1.start(); Thread t2 = new Thread(pt, "t2"); t2.start(); t1.join(); t2.join(); System.out.println("Processing count=" + pt.getCount()); >> class ProcessingThread implements Runnable < private int count; @Override public void run() < for (int i = 1; i < 5; i++) < processSomething(i); count++; >> public int getCount() < return this.count; >private void processSomething(int i) < // processing some job try < Thread.sleep(i * 1000); >catch (InterruptedException e) < e.printStackTrace(); >> > 

Если вы запустите вышеуказанную программу, вы заметите, что значение count варьируется между 5,6,7,8. Причина в том, что count++ не является атомарной операцией. Таким образом, к тому времени, когда один поток прочитает это значение и увеличит его на единицу, другой поток прочитает более старое значение, что приведет к неправильному результату. Чтобы решить эту проблему, нам нужно убедиться, что операция приращения счетчика является атомарной, мы можем сделать это с помощью синхронизации, но Java 5 java.util.concurrent.atomic предоставляет классы-оболочки для int и long, которые можно использовать для выполнения этой атомарной операции без использования синхронизации.

Пример Java AtomicInteger

Вот обновленная программа, которая всегда будет выводить значение счетчика как 8, потому что метод AtomicInteger incrementAndGet() атомарно увеличивает текущее значение на единицу.

package com.journaldev.concurrency; import java.util.concurrent.atomic.AtomicInteger; public class JavaAtomic < public static void main(String[] args) throws InterruptedException < ProcessingThread pt = new ProcessingThread(); Thread t1 = new Thread(pt, "t1"); t1.start(); Thread t2 = new Thread(pt, "t2"); t2.start(); t1.join(); t2.join(); System.out.println("Processing count=" + pt.getCount()); >> class ProcessingThread implements Runnable < private AtomicInteger count = new AtomicInteger(); @Override public void run() < for (int i = 1; i < 5; i++) < processSomething(i); count.incrementAndGet(); >> public int getCount() < return this.count.get(); >private void processSomething(int i) < // processing some job try < Thread.sleep(i * 1000); >catch (InterruptedException e) < e.printStackTrace(); >> > 

Преимущества использования классов Concurrency для атомарных операций заключаются в том, что нам не нужно беспокоиться о синхронизации. Это улучшает читаемость кода и снижает вероятность ошибок. Также предполагается, что классы параллелизма атомарных операций более эффективны, чем синхронизация, которая включает блокировку ресурсов.

Все права защищены. © Linux-Console.net • 2019-2023

Atomicinteger java что это

int значение, которое может быть обновлено атомарно. См. java.util.concurrent.atomic спецификация пакета для описания свойств атомарных переменных. AtomicInteger используется в приложениях, таких как атомарно постепенно увеличенные счетчики, и не может использоваться в качестве замены для Integer . Однако, этот класс действительно расширяется Number предоставить универсальный доступ инструментами и утилитами, которые имеют дело с в цифровой форме на основе классами.

Сводка конструктора

Создает новый AtomicInteger с начальным значением 0 .
Создает новый AtomicInteger с данным начальным значением.

Сводка метода

Методы

Модификатор и Тип Метод и Описание
int addAndGet(int delta)

Атомарно добавляет данное значение к текущей стоимости.

Атомарно устанавливает значение в данное обновленное значение если текущая стоимость == математическое ожидание.

Атомарно декременты одним текущая стоимость.
Возвращает значение конкретного количества как a double .
Возвращает значение конкретного количества как a float .
Получает текущую стоимость.
Атомарно добавляет данное значение к текущей стоимости.
Атомарно декременты одним текущая стоимость.
Атомарно инкременты одним текущая стоимость.
Атомарно наборы к данному значению и возвратам старое значение.
Атомарно инкременты одним текущая стоимость.
Возвращает значение конкретного количества как int .
В конечном счете наборы к данному значению.
Возвращает значение конкретного количества как a long .
Наборы к данному значению.
Возвращает Строковое представление текущей стоимости.

Атомарно устанавливает значение в данное обновленное значение если текущая стоимость == математическое ожидание.

Методы java.lang унаследованный от класса. Число

Методы java.lang унаследованный от класса. Объект

Деталь конструктора

AtomicInteger
public AtomicInteger(int initialValue)

Создает новый AtomicInteger с данным начальным значением.

AtomicInteger
public AtomicInteger()

Создает новый AtomicInteger с начальным значением 0 .

Деталь метода

добраться
public final int get()

Получает текущую стоимость.

набор
public final void set(int newValue)

Наборы к данному значению.

lazySet
public final void lazySet(int newValue)

В конечном счете наборы к данному значению.

getAndSet
public final int getAndSet(int newValue)

Атомарно наборы к данному значению и возвратам старое значение.

compareAndSet
public final boolean compareAndSet(int expect, int update)

Атомарно устанавливает значение в данное обновленное значение если текущая стоимость == математическое ожидание.

weakCompareAndSet
public final boolean weakCompareAndSet(int expect, int update)

Атомарно устанавливает значение в данное обновленное значение если текущая стоимость == математическое ожидание. Может перестать работать побочно и не обеспечивает гарантии упорядочивания, так только редко соответствующая альтернатива compareAndSet .

getAndIncrement
public final int getAndIncrement()

Атомарно инкременты одним текущая стоимость.

getAndDecrement
public final int getAndDecrement()

Атомарно декременты одним текущая стоимость.

getAndAdd
public final int getAndAdd(int delta)

Атомарно добавляет данное значение к текущей стоимости.

incrementAndGet
public final int incrementAndGet()

Атомарно инкременты одним текущая стоимость.

decrementAndGet
public final int decrementAndGet()

Атомарно декременты одним текущая стоимость.

addAndGet
public final int addAndGet(int delta)

Атомарно добавляет данное значение к текущей стоимости.

toString
public String toString()

Возвращает Строковое представление текущей стоимости.

intValue
public int intValue()

Описание скопировало с класса: Number
Возвращает значение конкретного количества как int . Это может включить округление или усечение.

longValue
public long longValue()

Описание скопировало с класса: Number
Возвращает значение конкретного количества как a long . Это может включить округление или усечение.

floatValue
public float floatValue()

Описание скопировало с класса: Number
Возвращает значение конкретного количества как a float . Это может включить округление.

doubleValue
public double doubleValue()

Различия между atomic, volatile и synchronized в Java

Прежде всего, необходимо понять, что это ключевые слова в языке программирования Java, которые используются для обеспечения корректной работы многопоточных приложений. Они помогают обеспечить, что при одновременном доступе нескольких потоков к одному и тому же ресурсу, не возникает конфликтов и ошибок.

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

Atomic

Atomic в Java представляет собой классы в пакете java.util.concurrent.atomic, которые позволяют выполнять атомарные операции. То есть, эти операции выполняются как единое целое и не могут быть прерваны.

В примере с счетчиком можно использовать AtomicInteger. Метод incrementAndGet() этого класса атомарно увеличивает значение счетчика на один и возвращает новое значение. Таким образом, даже если два потока одновременно вызовут этот метод, счетчик корректно увеличится на два.

Volatile

Ключевое слово volatile в Java гарантирует, что значение переменной будет сразу же записано в основную память, а не в кэш процессора, и любые другие потоки будут видеть это обновленное значение.

Вернемся к примеру с счетчиком. Если объявить счетчик как volatile int, то любые изменения его значения будут сразу же записаны в основную память, и другие потоки будут видеть это новое значение. Однако это не гарантирует атомарности операций. То есть, если два потока одновременно прочитают значение счетчика, увеличат его на один и запишут обратно, проблема с увеличением счетчика только на один, а не на два, все еще останется.

Synchronized

Ключевое слово synchronized в Java используется для обозначения блоков кода или методов, которые могут быть выполнены только одним потоком в одно и то же время.

Если применить synchronized к методу увеличения счетчика, то в любой момент времени только один поток сможет выполнить этот метод. Если другой поток попытается выполнить этот метод в то же время, он будет ждать, пока первый поток не завершит работу.

В заключении стоит отметить, что выбор между atomic, volatile и synchronized зависит от конкретной ситуации. В некоторых случаях может быть достаточно использовать volatile, в других может потребоваться более строгая синхронизация с помощью synchronized или atomic.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *