Рубрики
Без рубрики

Атомарный регистр на Java

Атомный счетчик. Пример Java AtomicInteger. Атомарная операция на java. Атомарная целочисленная переменная. Классы атомарного параллелизма Java java.util.concurrent.atomic

Автор оригинала: Pankaj Kumar.

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

Атомный регистратор

Давайте создадим простую многопоточную программу, в которой каждый поток увеличивает общую переменную count в 4 раза. Поэтому, если есть два потока, после их завершения количество значение должно быть 8.

Давайте создадим простую многопоточную программу, в которой каждый поток увеличивает общую переменную || count || в 4 раза. Поэтому, если есть два потока, после их завершения || количество || значение должно быть 8.

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();
        }
    }

}

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