当前位置: 首页 > 知识库问答 >
问题:

AtomicInteger真的产生原子整数吗?

邓业
2023-03-14
public class TestAtomicInteger {

public static void main(String[] args) {

    final AtomicInteger sequencer = new AtomicInteger(1);
    final Set<Integer> integers = new HashSet<>();
    //final Set<Integer> integers = new ConcurrentSkipListSet<>();


    final Runnable task = new Runnable() {

        @Override
        public void run() {
            int next = sequencer.getAndIncrement();
            integers.add(next);
            System.out.println(integers.size());
        }
    };
    for (int i = 0; i < 1000; i++) {
        Thread t = new Thread(task);
        t.start();
    }
}
}

有人解释一下为什么吗?多谢了。

*注意:在运行函数中。如果我使用System.out.println(next);有时我也会看到一些丢失的测序器。*

示例输出1:

共有1个答案

董桐
2023-03-14

代码的一个主要问题是将数字添加到不是线程安全的hashset中。这就是你所观察的原因。如果使用线程安全集合,则会得到预期的结果:

final Set<Integer> integers = new ConcurrentSkipListSet<>();

但这引入了一个额外的同步层。另一种选择是使用普通数组int[]numbers=new int[1000];并使用:numbers[next-1]++;来计算发生的次数。

供参考的新代码:

public static void main(String[] args) throws Exception {

    final AtomicInteger sequencer = new AtomicInteger(1);
    final int[] integers = new int[1000];

    final Runnable task = new Runnable() {

        @Override
        public void run() {
            int next = sequencer.getAndIncrement();
            integers[next-1]++;
        }
    };
    List<Thread> threads = new ArrayList<>();
    for (int i = 0; i < 1000; i++) {
        Thread t = new Thread(task);
        t.start();
        threads.add(t);
    }
    for (Thread t : threads) {
        t.join();
    }
    for (int i = 0; i < 1000; i++) {
        if (integers[i] != 1) System.out.println(i + " -> " + integers[i]);
    }
}
 类似资料:
  • 问题内容: 我已经读到,使用原子包类使我们能够做到线程安全,减少代码锁定。但是我不确定原子包类中的方法如何在不使用锁或任何syncize关键字的情况下如何提供线程安全性。任何帮助将不胜感激。 问题答案: 他们使用非常低级的指令,例如Compare和Swap,以及sun.misc.Unsafe类中的多种其他方法。 基本上,像这样的方法调用将对应于唯一的处理器指令,从而消除了许多多线程问题。

  • java.util.concurrent.atomic.AtomicInteger类提供对底层int值的操作,可以原子方式读取和写入,还包含高级原子操作。 AtomicInteger支持底层int变量的原子操作。 它具有get和set方法,类似于对volatile变量的读写操作。 也就是说,集合与同一变量上的任何后续获取具有先发生关系。 原子compareAndSet方法也具有这些内存一致性功能。

  • $RANDOM是Bash的一个返回伪随机 [1]整数(范围为0 - 32767)的内部函数(而不是一个常量或变量),它不应该用于产生加密的密钥. 例子 9-24. 产生随机整数 1 #!/bin/bash 2 3 # 每次调用$RANDOM都会返回不同的随机整数. 4 # 范围为: 0 - 32767 (带符号的16位整数). 5 6 MAXCOUNT=10

  • 问题内容: 这是故意的吗?我强烈记得以前的版本返回了吗?我该怎么办,有没有新的分公司运营商,或者我必须始终选拔? 问题答案: 更改除法运算符

  • 本文向大家介绍C#产生一个随机整数,包括了C#产生一个随机整数的使用技巧和注意事项,需要的朋友参考一下 示例 本示例生成0到2147483647之间的随机值。            

  • 问题内容: 更好写吗 要么 我认为第二个更好,应该更快并且更多的内存优化。但是他们不平等吗? 问题答案: 为了提高性能,通常最好使代码尽可能简单明了,并且通常会表现良好(因为JIT会最优化该代码)。就您而言,最简单的示例也可能是最快的。 我要么做 或更长的版本 要么 如果不需要,最好不要创建对象。 性能明智,第一是最好的。 如果您确定不会溢出,可以使用 您不会比这更快。