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
做到了这一点