Ява атомных операций - PullRequest
       6

Ява атомных операций

4 голосов
/ 10 августа 2010

Правильно разделить следующие операторы:

int v = ++j;

как:

  1. читать значение j (атомарный);
  2. увеличивать на 1 читать значение(NON атомарный возможно вмешательство в другой поток);
  3. записать результат добавления в i (атомарный);
  4. записать i в v (атомарный)

Ответы [ 4 ]

8 голосов
/ 10 августа 2010

Да, int (или меньшие типы данных) операции чтения / записи / арифметики являются атомарными. Ссылки (чтение / запись) также являются атомарными, независимо от того, 32-битные они или 64-битные.

Однако операции на 64-битных long и double могут быть не атомарными.

JLS 17,7 Неатомарная обработка double и long

В некоторых реализациях может оказаться удобным разделить одно действие записи для 64-разрядного значения long или double на два действия записи для смежных 32-разрядных значений. Ради эффективности это поведение зависит от конкретной реализации; Виртуальные машины Java могут выполнять запись в значения long и double атомарно или из двух частей.

Для целей модели памяти языка программирования Java одна запись в значение, отличное от volatile long или double, рассматривается как две отдельные записи: по одной на каждую 32-битную половину. Это может привести к ситуации, когда поток видит первые 32 бита 64-битного значения из одной записи и вторые 32 бита из другой записи. Запись и чтение значений volatile long и double всегда являются атомарными. Запись и чтение ссылок всегда являются атомарными, независимо от того, реализованы ли они как 32- или 64-битные значения.

Разработчикам виртуальных машин рекомендуется избегать разделения их 64-битных значений, где это возможно. Программистам рекомендуется объявлять общие 64-битные значения как volatile или синхронизировать свои программы правильно, чтобы избежать возможных осложнений.

Обратите внимание, что ни сами операторы ни до, ни после увеличения / уменьшения не являются атомарными, даже на int или byte: операции чтения / записи / арифметики выполняются в виде отдельных шагов.

Смотри также

1 голос
/ 10 августа 2010

Да, ваше предположение верно.Увеличение int приводит к трем шагам (таким образом, оно не является атомарным), назначение его - еще один шаг.Вот результирующий байт-код:

..
istore_1
iinc    1, 1
iload_1
istore_2
..
1 голос
/ 10 августа 2010

Закрыть.Шаг 2 атомарный.В этом случае j должно быть одним из byte, char, short или int, и каждый из них может быть загружен и сохранен атомарно.

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

0 голосов
/ 10 августа 2010

Я бы использовал AtomicInteger

AtomicInteger j; // do init

int v = j.incrementAndGet();

Быстрый просмотр с JAD показывает следующий байт-код для инструкций:

    int j = 0;
//    0    0:iconst_0
//    1    1:istore_1
    int v = ++j;
//    2    2:iinc            1  1
//    3    5:iload_1
//    4    6:istore_2
...