use*_*424 13 java concurrency multithreading atomic compare-and-swap
由于Integer类也是不可变类,我们知道不可变类是线程安全的,因此需要Atomic Integer.我很迷惑 .这是因为读取和写入不可变对象不必是原子的,而原子整数的读写是原子的.这意味着原子类也是线程安全的.
AtomicInteger 是线程安全的(事实上,java.util.concurrent.atomic 包中的所有类都是线程安全的),而普通整数不是线程安全的。
当您在多线程环境中使用“整数”变量(以使其线程安全)时,您将需要“同步”和“易失性”关键字,而对于原子整数,您不需要“同步”和“易失性”作为原子整数的关键字负责线程安全。
另外,我会推荐以下关于同一主题的有用教程: http://tutorials.jenkov.com/java-concurrency/compare-and-swap.html
有关“atomic”包的更多信息,请参阅下面的 oracle 文档: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html
当您需要确保只有一个线程可以更新int变量时,AtomicInteger用于多线程环境.优点是不需要外部同步,因为修改它的值的操作是以线程安全的方式执行的.
考虑followind代码:
private int count;
public int updateCounter() {
return ++count;
}
Run Code Online (Sandbox Code Playgroud)
如果多个线程调用updateCounter方法,则有些线程可能会收到相同的值.因为++计数操作不是原子的,因为它不仅是一个操作,而是由三个操作组成:read count, add 1 to it's value and write it back to it.多个调用线程可以将变量视为未修改为其最新值.
上面的代码应替换为:
private AtomicInteger count = new AtomicInteger(0);
public int updateCounter() {
return count.incrementAndGet();
}
Run Code Online (Sandbox Code Playgroud)
incrementAndGet保证该方法以原子方式递增存储的值并返回其值而不使用任何外部同步.
如果你的值永远不会改变,你不必使用AtomicInteger,它应该使用int.
考虑一个变量
int myInt = 3;
Run Code Online (Sandbox Code Playgroud)
AtomicInteger涉及到myInt。
Integer涉及到3。
换句话说,你的变量是可变的并且可以改变它的值。而值 3 是一个整数文字、一个常量、一个不可变的表达式。
整数是文字的对象表示,因此是不可变的,你基本上只能读取它们。
AtomicIntegers 是这些值的容器。您可以读取并设置它们。与给变量赋值相同。但与改变变量的值不同int,对 an 的操作AtomicInteger是原子的。
例如,这不是原子的
if(myInt == 3) {
myInt++;
}
Run Code Online (Sandbox Code Playgroud)
这是原子的
AtomicInteger myInt = new AtomicInteger(3);
//atomic
myInt.compareAndSet(3, 4);
Run Code Online (Sandbox Code Playgroud)