有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

使用AtomicInteger与静态int的原子Java

在使用多线程的过程中,我学会了在需要使用多线程访问的计数器时使用静态变量

例如:

static int count=0;然后在程序的后面我将其用作count++;

今天我遇到了一个名为AtomicInteger的方法,我还了解到它是线程安全的,可以使用它的一个名为getAndInrement()的方法来实现同样的效果

有谁能帮我了解一下使用static atomicIntegerstatic int count的区别吗


共 (6) 个答案

  1. # 1 楼答案

    static int counter将在multithreaded环境中给您不一致的结果,除非您使计数器volatile或使增量块synchronized

    automic的情况下,它给出了单变量的lock-free{}编程

    更多详情请参见automic'slink

  2. # 2 楼答案

    -AtomicInteger用于对整数执行原子运算,当您不想使用synchronized关键字时,它是另一种选择

    -在非原子场上使用volatile会产生不一致的结果

    int volatile count;
    
    public void inc(){
    
    count++
    
    }
    

    -static将使该类的所有实例共享一个变量,但仍然会在多线程环境中产生不一致的结果

    所以,在多线程环境中尝试以下方法:

    1遵循布莱恩法则总是更好的:

    When ever we write a variable which is next to be read by another thread, or when we are reading a variable which is written just by another thread, it needs to be synchronized. The shared fields must be made private, making the read and write methods/atomic statements synchronized.

    2第二个选项是使用Atomic Classes,比如AtomicInteger, AtomicLong, AtomicReference, etc.

  3. # 3 楼答案

    我认为没有保证能在count++上看到最新的价值count++必须读取count的值。另一个Thread可以将新值写入count,但将其值存储在Thread本地缓存上,即不刷新到主内存。同样,你的Thread,即读取count,也不能保证从主存读取,即从主存刷新synchronize保证了这一点

  4. # 4 楼答案

    有了AtomicIntegerincrementAndGet()保证是原子的
    如果使用count++来获取前一个值,则不能保证它是原子的


    我从你的问题中漏掉了一些东西——其他答案也说明了这一点——静态与线程无关

  5. # 5 楼答案

    我同意@Kumar的回答

    Volatile是不够的——它对内存顺序有一些影响,但不能确保++的原子性

    多线程编程真正困难的地方在于,在任何合理的测试量中,问题可能都不会出现。我编写了一个程序来演示这个问题,但它的线程只执行增量计数器。即便如此,计数仍在正确答案的1%以内。在一个实际的程序中,如果两个线程有其他工作要做,那么两个线程进行++运算的概率可能很低,足以同时显示问题。多线程正确性不能在中测试,它必须在中设计

    这个程序使用简单的静态int、volatile int和AtomicInteger执行相同的计数任务。只有原子整数始终得到正确答案。具有4个双线程内核的多处理器上的典型输出为:

    count: 1981788 volatileCount: 1982139 atomicCount: 2000000 Expected count: 2000000
    

    以下是源代码:

      import java.util.ArrayList;
      import java.util.List;
      import java.util.concurrent.atomic.AtomicInteger;
    
      public class Test {
        private static int COUNTS_PER_THREAD = 1000000;
        private static int THREADS = 2;
    
        private static int count = 0;
        private static volatile int volatileCount = 0;
        private static AtomicInteger atomicCount = new AtomicInteger();
    
        public static void main(String[] args) throws InterruptedException {
          List<Thread> threads = new ArrayList<Thread>(THREADS);
          for (int i = 0; i < THREADS; i++) {
            threads.add(new Thread(new Counter()));
          }
          for (Thread t : threads) {
            t.start();
          }
          for (Thread t : threads) {
            t.join();
          }
          System.out.println("count: " + count +  " volatileCount: " + volatileCount + " atomicCount: "
              + atomicCount + " Expected count: "
              + (THREADS * COUNTS_PER_THREAD));
        }
    
        private static class Counter implements Runnable {
          @Override
          public void run() {
            for (int i = 0; i < COUNTS_PER_THREAD; i++) {
              count++;
              volatileCount++;
              atomicCount.incrementAndGet();
            }
          }
        }
      }
    
  6. # 6 楼答案

    “静态”使变量成为类级别。这意味着,如果在一个类中定义“static int count”,那么无论创建了多少个类实例,所有实例都使用相同的“count”。虽然AtomicInteger是一个普通类,但它只是添加了同步保护