概述
前言:
AtomicInteger
是一个专门用于以线程安全方式更新整数设计的类。 为什么我们不能简单地使用volatile int ?
AtomicInteger
//非线程安全计数器 volatile int
public class CounterNotThreadSafe {
private volatile int count = 0;
public void increment() {
count++;
}
public int getCount() {
return count;
}
}
计数存储在volatile int #2行。使用volatile关键字来确保线程始终看到当前值(说明)。我们使用#4行的操作来递增计数器。检查是否是线程安全的使用以下测试:
public class ConcurrencyTestCounter {
private final CounterNotThreadSafe counter = new CounterNotThreadSafe();
@Interleave
private void increment() {
counter.increment();
}
@Test
public void testCounter() throws InterruptedException {
Thread first = new Thread( () -> { increment(); } ) ;
Thread second = new Thread( () -> { increment(); } ) ;
first.start();
second.start();
first.join();
second.join();
assertEquals( 2 , counter.getCount());
}
}
启动两个线程然后两个线程都使用线程join
两个线程停止后,检查计数是否为2。
使用Interleave
来自vmlens ;Interleave
注解告诉 vmlens
测试所有线程的交错的批注的方法。运行测试出现以下错误:
#逾期应该是:2 ; 但实际是:1
ConcurrencyTestCounter.testCounter:22 expected:<2> but was:<1>
原因是 ++
不是原子操作,两个线程可以覆盖另一个线程的结果。两个线程首先并行读取变量计数。然后都写入变量。就会导致错误的值=1。vmlens报告:
使用AtomicInteger
public class CounterUsingIncrement {
private final AtomicInteger count = new AtomicInteger();
public void increment() {
count.incrementAndGet();
}
public int getCount() {
return count.get();
}
}
或者:
public void increment() {
int current = count.get();
int newValue = current + 1;
while( ! count.compareAndSet( current , newValue ) ) {
current = count.get();
newValue = current + 1;
}
}
现在由于该方法 incrementAndGet
是原子的,另一个线程总是在方法调用之前或之后看到该值,因此线程不能覆盖其计算的值。因此对于所有线程交错,计数现在总是=2。
结论
AtomicInteger
让我们以线程安全的方式更新整数。使用像incrementAndGet
或 decrementAndGet
的原子方法计算。并使用方法get和compareAndSet
进行计算。
最后
以上就是心灵美牛排为你收集整理的Java并发 AtomicInteger的全部内容,希望文章能够帮你解决Java并发 AtomicInteger所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复