我正在阅读有关AtomicInteger的内容,以及它的操作是原子的以及这些属性如何使其对多线程有用。
我编写了以下程序来进行测试。
我期望该集合的最终大小应该为1000,因为每个线程循环执行500次,并假设每次线程调用getNext()时,它应该获得一个唯一的数字。
但是输出总是小于1000。我在这里缺少什么?
public class Sequencer {
private final AtomicInteger i = new AtomicInteger(0);
public int getNext(){
return i.incrementAndGet();
}
public static void main(String[] args) {
final Sequencer seq = new Sequencer();
final Set<Integer> set = new HashSet<Integer>();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i=0; i<500; i++)
set.add(seq.getNext());
}
},"T1");
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i=0; i<500; i++)
set.add(seq.getNext());
}
},"T2");
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(set.size());
}
}
您缺少HashSet不是线程安全的。另外,集合的属性将删除所有重复的数字,因此,如果AtomicInteger不是线程安全的,则测试将失败。
编辑:因为已经被询问过两次:使用同步集有效,但是它破坏了使用诸如Atomic-classes之类的无锁算法的想法。如果在上面的代码中用同步集替换了该集,则每次add
调用时线程将不得不阻塞。
这将有效地将您的应用程序减少到单线程,因为完成的唯一工作是同步进行的。实际上,它甚至会比单线程慢,因为synchronized
它也要付出代价。因此,如果您想实际利用线程,请尽量避免synchronized
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句