java - AtomicInteger 增量未按预期运行

标签 java multithreading concurrency atomic atomicinteger

我正在阅读有关 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 不是线程安全的,您的测试将失败。

尝试使用 ConcurrentLinkedQueue相反。

编辑:因为它被问了两次:使用同步集可行,但它破坏了使用像原子类这样的无锁算法背后的想法。如果在上面的代码中用同步集替换集合,则每次调用 add 时线程都必须阻塞。

这将有效地将您的应用程序减少到单线程,因为唯一完成的工作是同步的。实际上它甚至会比单线程慢,因为 synchronized 也会产生影响。因此,如果您想真正利用线程,请尽量避免 synchronized

关于java - AtomicInteger 增量未按预期运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21354409/

相关文章:

Java GUI Xmonad 不工作

java - 在java中使用泛型编写方法时<E>到底做了什么?

java - 在 java 线程内停止播放器 (JLayer)

multithreading - JDBC提交失败,在autocommit = true时调用提交。多线程 hibernate session 以某种方式更改了自动提交?

c++ - "C++ Concurrency in Action"中的阿姆达尔定律

java - 关于ConcurrentLinkedQueue

java - 我不明白如何显示我的计算

java - 如果语句和 && 给出 IDE 错误 'Syntax error on token "=", <= expected'

类方法上的python线程计时器

language-agnostic - 函数式编程 : immutability etc