Java-使用AtomicInteger与静态int

Java-使用AtomicInteger与静态int,java,atomic,Java,Atomic,在使用多线程的过程中,我学会了在需要使用多线程访问的计数器时使用静态变量 例如: static int count=0之后在程序中,我将其用作count++ 今天我遇到了一个叫做AtomicInteger的东西,我还了解到它是线程安全的,可以使用它的一个名为getAndInrement()的方法来实现同样的效果 有谁能帮我了解一下使用静态atomicInteger与静态int count的区别吗?使用atomicInteger的incrementAndGet()保证是原子的。 如果使用count

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

例如:

static int count=0之后在程序中,我将其用作
count++

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


有谁能帮我了解一下使用
静态atomicInteger
静态int count
的区别吗?

使用
atomicInteger
incrementAndGet()
保证是原子的。
如果使用
count++
获取上一个值,则不能保证它是原子的



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

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

静态int计数器
会在
多线程
环境中产生不一致的结果,除非您使计数器
易变
或使增量块同步

automic
的情况下,它对单个变量进行
无锁
线程安全
编程


关于和

的更多细节,我认为无法保证在
count++
上看到最新的值
count++
必须读取
count
的值。另一个
线程
可以将新值写入
计数
,但将其值存储在
线程
本地缓存中,即。E不刷新到主内存。另外,读取
计数的
线程
,也不能保证从主内存读取,即。E从主存刷新<代码>同步
保证。

AtomicInteger将get和增量作为一个原子进程。它可以被认为是数据库中的序列器。它提供了递增、递减增量int值的实用方法


如果您获取计数器,然后处理并更新它,则static int可能会导致问题。AtomicInteger操作简单,但如果必须根据处理结果更新计数器,则不能使用它。

-
AtomicInteger
用于对整数执行原子操作,当您不想使用
synchronized
关键字时,它是一种替代方法

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

int volatile count;

public void inc(){

count++

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

int volatile count;

public void inc(){

count++

}
因此,在多线程环境中尝试以下方法:

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

当我们写一个变量,而下一个变量将被另一个变量读取时 线程,或者当我们正在读取一个由 另一个线程,它需要同步。共享字段必须为空 私有化,使读写方法/原子语句 同步的


2.第二个选项是使用
原子类,如
原子整数、原子长、原子引用等。

我同意@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();
        }
      }
    }
  }
import java.util.ArrayList;
导入java.util.List;
导入java.util.concurrent.AtomicInteger;
公开课考试{
每个线程的私有静态int计数=1000000;
私有静态int线程=2;
私有静态整数计数=0;
私有静态volatile int volatileCount=0;
私有静态AtomicInteger atomicCount=新的AtomicInteger();
公共静态void main(字符串[]args)引发InterruptedException{
列表线程=新的ArrayList(线程);
对于(int i=0;i
您必须自己保护对
int
的并发访问。但是,
AtomicInteger
被设计成线程安全的。
static
做到了这一点