Какой Java-эквивалент класса .Net Interlocked?

Как мне модифицировать int с помощью атомарного и потокобезопасного использования в Java?

Атомно увеличивать, тестировать и устанавливать, и т.д...?

Ответы

Ответ 2

Безопасность потоков может быть достигнута с помощью синхронизированных функций. Оберните свой int (или такие данные) в классе, который обеспечивает требуемые функции с помощью синхронизированных методов, например

public class X
{
  protected int x;
  public synchronized void set( int value )
  {
    x = value;
  }
}

Вы также можете использовать классы из пакета java.util.concurrent.atomic, например. AtomicInteger или AtomicIntegerArray

Почему этот ответ не будет работать

Я просто хотел точно указать, что не так с этим ответом, в случае, если любые вещи, которые synchronized могут быть использованы для решения эффектов расы нити

| Thread A      | Thread B         | 
|---------------|------------------|
| read x (x=4)  |                  |
|               | read x (x=4)     |
| Calculate 4+1 |                  |
| EAX ← 5       |                  |
|               | Calculate 4+1    |
|               | EAX ← 5          |
| Start sync    |                  |
| {             | Start sync       |
| { x ← 5       |    wait          |
| {             |    wait          |
| End sync      |    wait          |
|               | {                | 
|               | { x ← 5          |
|               | {                | 
|               | End sync         |

Конечный результат операций:

x = 4;
x += 1;
x += 1;

- это x = 5, а не 6.

Такая же проблема существует с ключевым словом volatile. Ключевое слово volatile не избавляет вас от эффектов потоков. Ключевое слово volatile гарантирует, что

  • кэши очищаются до чтения переменной.
  • кэши очищаются после записи значения

Строго говоря, volatile гарантирует, что операции памяти не переупорядочиваются вокруг изменчивой переменной. Это означает, что вы по-прежнему страдают от:

  • читать с x
  • записать в x

проблема.

Ответ 3

private final static AtomicInteger at = new AtomicInteger();

public void run() {
    at.set(7);
    int i = at.incrementAndGet();