好吧,这是一个你可以写一个快速的“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());
}
}
最后,两个计数器都应该并且将都是 0。通过删除“同步”关键字,您将看到事情完全出错。
所以,是的,两者都实现了同样的事情:线程安全性。
Oracle 记录了下面的例子:https://docs.oracle.com/javase/tutorial/essential/concurrency/atomicvars.html
对于这个简单的类,同步是一个可接受的解决方案。但对于更复杂的类,我们可能希望避免不必要的同步对活动性的影响。用 AtomicInteger 替换 int 字段可以防止线程干扰,而无需诉诸同步
最后,如果您需要显式同步或原子场就足够了,则方法的行为将有所不同。