AtomicLong в многопоточности - PullRequest
0 голосов
/ 04 апреля 2020

Я пытаюсь использовать AtomicLong в многопоточной среде. Мой желаемый результат не работает,

public class Account implements Runnable {

    private final AtomicLong amount = new AtomicLong(0);

    public Account(long difference) {
        amount.set(difference);
    }

    public void run() {
        System.out.println("The Balance is : " + amount);
    }
}
public class Examples {
    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(10);
        IntStream.range(0, 100).forEach(i -> service.submit(new Account(i)));
    }
}

Я пытался использовать блокировку чтения / записи и синхронизацию на уровне блоков, но безуспешно. Может, кто-нибудь подскажет, где я делаю ошибку?

У меня вывод должен начинаться с 0,1,2 ... 99.

Ответы [ 2 ]

3 голосов
/ 04 апреля 2020

Нет данных, которыми вы делитесь между вашими потоками ... каждая создает свою собственную AtomicLong, без обмена Даже если он будет передан, не будет никакой гарантии, что числа будут напечатаны по порядку. Они даже не гарантируют, что все числа будут напечатаны (некоторые из них могут быть напечатаны более одного раза).

Если я изменю ваш код следующим образом:

public static class Account implements Runnable {
    private static final AtomicLong amount = new AtomicLong(0);

    public Account(long difference) {
        amount.set(difference);
    }

    public void run() {
        System.out.println("The Balance is : " + amount);
    }
}

Вот пример я получаю вывод:

The Balance is : 2
The Balance is : 2
The Balance is : 2
The Balance is : 4
The Balance is : 5
The Balance is : 6
The Balance is : 7
The Balance is : 8
The Balance is : 9
The Balance is : 9

Причина в том, что возможен следующий сценарий:

  • основной поток создает Account(0). Это записывает 0 в общий AtomicLong.,
  • Thread-0 запускается
  • основной поток создает Account(1). Это записывает 1 в общий AtomicLong.
  • Thread-0 выводит значение, теперь оно 1. В этом случае 0 никогда не будет напечатано.

Единственное, что AtomicLong гарантирует вам, это то, что все записи в значение всегда будут видны всем потокам, выполняющим чтение впоследствии.

Свойства переменных atomi c подробно описаны в javado c (см. здесь ).

0 голосов
/ 04 апреля 2020

Возможно, вы имели в виду что-то подобное:

public class Account implements Runnable {

    private final static AtomicLong seq = new AtomicLong(0);
    private final long amount;

    public Account() {
        amount = seq.getAndIncrement();
    }

    public void run() {
        System.out.println("The Balance is : " + amount);
    }
}

public class Examples {
    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(10);
        IntStream.range(0, 100).forEach(i -> service.submit(new Account()));
    }
}

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

...