Kul*_*eep 8 java multithreading atomicity java.util.concurrent
我有一个具有递增和递减方法的计数器类,两个方法都是同步的.
public class Counter {
int count = 0;
public synchronized void increment(){
count++;
}
public synchronized void decrement(){
count--;
}
}
Run Code Online (Sandbox Code Playgroud)
从这个例子可以看出,竞争条件不会发生,只有一个线程可以访问增量或减量方法.
现在代替整数原语,如果我用Atomic Integer修改了计数器类并删除了synchronized关键字,我们可以实现同样的目的吗?
public class Counter {
AtomicInteger count = new AtomicInteger();
public void increment(){
count.incrementAndGet();
}
public void decrement(){
count.decrementAndGet();
}
}
Run Code Online (Sandbox Code Playgroud)
嗯,这就是你可以编写一个快速的“n”脏程序来评估的问题:
public class ThreadExperiment {
public static class CounterSync {
int count = 0;
public synchronized void increment(){
count++;
}
public synchronized void decrement(){
count--;
}
}
public static class CounterAtomic {
AtomicInteger count = new AtomicInteger();
public void increment(){
count.incrementAndGet();
}
public void decrement(){
count.decrementAndGet();
}
}
public static void main(String[] args) throws InterruptedException {
final CounterSync counterSync = new CounterSync();
final CounterAtomic counterAtomic = new CounterAtomic();
Runnable runnable = () -> {
for (int i = 0; i < 1_000_000; i++) {
int j = i & 1;
if (j == 0) {
counterSync.increment();
counterAtomic.increment();
} else {
counterSync.decrement();
counterAtomic.decrement();
}
}
};
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(runnable);
}
for (Thread t : threads)
t.start();
for (Thread t : threads)
t.join();
System.out.println("Sync count = " + counterSync.count);
System.out.println("Atomic count = " + counterAtomic.count.intValue());
}
}
Run Code Online (Sandbox Code Playgroud)
最后,两个计数器都应该并且将是 0。通过删除“同步”关键字,您会发现事情完全出错了。
所以是的,两者都实现了相同的目标:线程安全。
Oracle 在此处记录示例:https : //docs.oracle.com/javase/tutorial/essential/concurrency/atomicvars.html
对于这个简单的类,同步是一个可以接受的解决方案。但是对于更复杂的类,我们可能希望避免不必要的同步对活跃度的影响。用 AtomicInteger 替换 int 字段允许我们在不诉诸同步的情况下防止线程干扰
最后,如果您需要显式同步或原子字段是否足够,您的方法的行为将有所不同。
从java-8有一个更好的(在真正的竞争环境中读取更快)选项开始,而不是AtomicInteger,它被调用LongAdder并且它以相同的方式保证原子更新:
在低更新争用下,这两个类具有相似的特征(AtomicLong).但在高争用的情况下,这一类的预期吞吐量明显更高,但代价是空间消耗更高.
它的实施非常棒.用简单的英语(简化):如果线程之间没有争用,那就不要聪明了,只需像AtomicLong那样工作; 如果有,请尝试为每个线程创建一个单独的工作空间,以便最大限度地减少争用.
它有你关心的相同方法:add和decrement.
| 归档时间: |
|
| 查看次数: |
1906 次 |
| 最近记录: |