由于Integer类也是不可变类,我们知道不可变类是线程安全的,因此需要Atomic Integer。 我很迷惑 。 这是因为读取和写入不可变对象不必是原子的,而原子整数的读写是原子的。 这意味着原子类也是线程安全的。
答案 0 :(得分:5)
当您需要确保只有一个线程可以更新int变量时,AtomicInteger用于多线程环境。优点是不需要外部同步,因为修改它的值的操作是以线程安全的方式执行的。
考虑以下代码:
private int count;
public int updateCounter() {
return ++count;
}
如果多个线程调用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();
}
incrementAndGet
方法保证以原子方式递增存储的值,并在不使用任何外部同步的情况下返回它的值。
如果你的价值永远不会改变,你就不必使用AtomicInteger,它应该使用int。
答案 1 :(得分:3)
虽然根据定义不可变对象是线程安全的,但是可变对象也可以是线程安全的。
这正是Atomic...
类(AtomicInteger
,AtomicBoolean
等等)的目的。
各种...get...
和...set...
方法允许线程安全访问和对象的变异。
毫不奇怪,该类在java.util.concurrent
包中声明。
您只需浏览java.util.concurrent.atomic
包的API:
一个小型工具包,支持对单个变量进行无锁线程安全编程。
答案 2 :(得分:2)
考虑一个变量
int myInt = 3;
AtomicInteger
与myInt
有关。
Integer
与3
有关。
整数是文字的对象表示,因此是不可变的,你基本上只能读它们。
AtomicIntegers是这些值的容器。您可以阅读和设置它们。与将值赋值给变量相同。但与更改int
变量的值不同,AtomicInteger
上的操作是原子的。
例如,这不是原子
if(myInt == 3) {
myInt++;
}
这是原子
AtomicInteger myInt = new AtomicInteger(3);
//atomic
myInt.compareAndSet(3, 4);
答案 3 :(得分:2)
AtomicInteger是线程安全的(实际上,java.util.concurrent.atomic包中的所有类都是线程安全的),而普通整数不是线程安全的。
你需要'同步'和& 'volatile'关键字,当你在多线程环境中使用'Integer'变量(使其线程安全)时,与原子整数一样,你不需要'synchronized'和& 'volatile'关键字作为原子整数来处理线程安全。
另外,我会推荐以下有用的教程: http://tutorials.jenkov.com/java-concurrency/compare-and-swap.html
有关'atomic'包的更多信息,请参阅下面的oracle doc: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html