W innych odpowiedziach wyjaśniono, dlaczego potrzebne jest AtomicInteger
. Chciałbym wyjaśnić, o czym mówi ten dokument.
Użycie terminu atomowego w tym dokumencie nie jest takie samo, jak jego użycie w AtomicInteger
.
Dokument stwierdza również
działania atomowe nie mogą być przeplatane, więc można je stosować bez obawy interferencji gwintu.
Odnosi się
int x;
x = 1; // thread 1
x = 2; // thread 2
System.out.println(x); // thread 3
thread 3
gwarantuje patrz albo wartość 1
lub wartość 2
.
Jednak z long
lub double
, nie masz tej gwarancji. Java Language Specification stwierdza
dla celów języka programowania Java model pamięci, a pojedynczego zapisu do nieulotnej long
lub double
wartości jest traktowany jako dwa oddzielne pisze: jeden do każdego 32-bitowego połowę. Może to spowodować sytuację, w której wątek widzi pierwsze 32 bity 64-bitowej wartości od jeden zapis, a drugi 32 bity od innego zapisu.
Tak więc, na przykład,
long x;
x = 0xffff_ffffL; // thread 1
x = 0x7fff_ffff_0000_0000L; // thread 2
System.out.println(x); // thread 3
thread 3
może zobaczyć pierwsze 32 bity z thread 1
'przeniesienie s, a ostatnie 32 bitów z thread 2
' przeniesienie s, tworząc wartość 7fff_ffff_ffff_ffff
long
. To samo może wystąpić dla double
.
Modyfikowanie zmiennej long
lub double
za pomocą volatile
zapobiega temu zjawisku.
Atomowość zapisu ma niewiele wspólnego z przypadkami "AtomicInteger". Na przykład. 'compareAndSet' jest nadal bardzo ważny i nie ma nic wspólnego z atomowością jego zapisów. – luk2302
Wszystkie prymitywy z wyjątkiem 'long' i' double' zawsze były atomowe dla odczytywania i zapisywania. To się nie zmieniło dla 'int'. –
Co, jeśli atomowość nie jest wszystkim, czego potrzebujesz? A jeśli potrzebujesz np. Gwarancji widoczności? –