[英]Java Volatile ,synchronization,atomic example
嗨,我正在實踐中閱讀Java並發性,並且閱讀了有趣的聲明,指出
鎖定可以保證可見性和原子性。 volatile變量只能保證可見性。
誰能解釋一下,如果將一個變量聲明為volatile,所有其他讀取線程都將獲得更新的值,那么為什么我要關心語句中的原子性,如: counter = counter + 1
;
提前致謝。
volatile關鍵字的影響大約是該變量上的每個讀寫操作都是原子的。
但是,值得注意的是,需要多個讀/寫操作(例如,i ++相當於i = i + 1,可以進行一次讀和一次寫操作)不是原子操作,因為另一個線程可能會向i寫入數據。在讀取和寫入之間。
像AtomicInteger和AtomicReference這樣的Atomic類在原子上提供了各種各樣的操作,特別是包括AtomicInteger的增量。
這就是為什么您需要關心諸如counter = counter + 1之類的語句中的原子性的原因
請檢查此帖子揮發性與原子性
這是一個自包含的示例可執行應用程序,演示了僅憑volatile是不夠的。 四個線程將每個計數器遞增10,000次,因此您希望計數器最后為40,000。 它使用原始的int變量和AtomicInt,並分別嘗試5次。
import java.util.Collections;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
class AtomicDemo {
interface Demo extends Callable<Void> {
int getCounter();
}
static class UsePrimitive implements Demo {
private volatile int counter = 0;
public Void call() throws Exception {
for (int i = 1; i <= 10000; ++i) {
++counter;
}
return null;
}
public int getCounter() {
return counter;
}
}
static class UseAtomic implements Demo {
final AtomicInteger counter = new AtomicInteger(0);
public Void call() throws Exception {
for (int i = 1; i <= 10000; ++i) {
counter.incrementAndGet();
System.out.print("");
}
return null;
}
public int getCounter() {
return counter.get();
}
}
public static void main(String[] args) throws Exception {
ExecutorService exec = Executors.newFixedThreadPool(4);
for (int i = 1; i <= 5; ++i) {
Demo demo = new UsePrimitive();
exec.invokeAll(Collections.nCopies(4, demo));
System.out.println("Count to 40000 using primitive, attempt number " + i + ": " + demo.getCounter());
}
for (int i = 1; i <= 5; ++i) {
Demo demo = new UseAtomic();
exec.invokeAll(Collections.nCopies(4, demo));
System.out.println("Count to 40000 using atomic, attempt number " + i + ": " + demo.getCounter());
}
exec.shutdownNow();
}
}
典型輸出:
Count to 40000 using primitive, attempt number 1: 39711
Count to 40000 using primitive, attempt number 2: 39686
Count to 40000 using primitive, attempt number 3: 39972
Count to 40000 using primitive, attempt number 4: 39840
Count to 40000 using primitive, attempt number 5: 39865
Count to 40000 using atomic, attempt number 1: 40000
Count to 40000 using atomic, attempt number 2: 40000
Count to 40000 using atomic, attempt number 3: 40000
Count to 40000 using atomic, attempt number 4: 40000
Count to 40000 using atomic, attempt number 5: 40000
您會看到,只有使用AtomicInt才能始終獲得預期的結果。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.