Java - 使用 AtomicInteger 与静态 int
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13598679/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java - using AtomicInteger vs Static int
提问by user547453
While using multiple threads I have learnt to use Static variables whenever I want to use a counter that will be accessed by multiple threads.
在使用多个线程时,我已经学会了使用静态变量,只要我想使用一个可以被多个线程访问的计数器。
Example:
例子:
static int count=0;
Then later in the program I use it as count++;
.
static int count=0;
然后在程序中我将它用作count++;
.
Today I came across something called AtomicInteger
and I also learned that it is Thread safe and could use one of its methods called getAndInrement()
to achieve the same effect.
今天我遇到了一个叫做的东西AtomicInteger
,我还了解到它是线程安全的,可以使用它调用的方法之一getAndInrement()
来实现相同的效果。
Could anyone help me to understand about using static atomicInteger
versus static int count
?
谁能帮助我了解使用static atomicInteger
vs static int count
?
回答by Kumar Vivek Mitra
-AtomicInteger
is used to perform the atomic operation over an integer, its an alternative when you don't want to use synchronized
keyword.
-AtomicInteger
用于对整数执行原子操作,当您不想使用synchronized
关键字时,它是一种替代方法。
-Using a volatile
on a Non-Atomic field will give inconsistent result.
-volatile
在非原子场上使用 a会产生不一致的结果。
int volatile count;
public void inc(){
count++
}
-static
will make a variable shared by all the instances of that class, But still it will produce an inconsistent result in multi-threading environment.
-static
将使该类的所有实例共享一个变量,但它仍然会在多线程环境中产生不一致的结果。
So try these when you are in multithreading environment:
所以当你在多线程环境中时试试这些:
1.Its always better to follow the Brian's Rule:
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.Second option is using the Atomic Classes
, like AtomicInteger, AtomicLong, AtomicReference, etc.
2.第二个选项是使用Atomic Classes
, 像AtomicInteger, AtomicLong, AtomicReference, etc.
回答by Patricia Shanahan
I agree with @Kumar's answer.
我同意@Kumar 的回答。
Volatile is not sufficient - it has some implications for the memory order, but does not ensure atomicity of ++.
Volatile 是不够的——它对内存顺序有一些影响,但不能确保 ++ 的原子性。
The really difficult thing about multi-threaded programming is that problems may not show up in any reasonable amount of testing. I wrote a program to demonstrate the issue, but it has threads that do nothing but increment counters. Even so, the counts are within about 1% of the right answer. In a real program, in which the threads have other work to do, there may be a very low probability of two threads doing the ++ close enough to simultaneously to show the problem. Multi-thread correctness cannot be tested in, it has to be designed in.
多线程编程真正困难的地方在于,在任何合理数量的测试中都可能不会出现问题。我写了一个程序来演示这个问题,但它的线程除了递增计数器外什么都不做。即便如此,计数仍然在正确答案的 1% 以内。在线程有其他工作要做的实际程序中,两个线程执行 ++ 以同时显示问题的可能性非常低。多线程正确性无法测试,必须设计。
This program does the same counting task using a simple static int, a volatile int, and an AtomicInteger. Only the AtomicInteger consistently gets the right answer. A typical output on a multiprocessor with 4 dual-threaded cores is:
这个程序使用一个简单的 static int、一个 volatile int 和一个 AtomicInteger 来完成相同的计数任务。只有 AtomicInteger 始终能得到正确的答案。具有 4 个双线程内核的多处理器上的典型输出是:
count: 1981788 volatileCount: 1982139 atomicCount: 2000000 Expected count: 2000000
Here's the source code:
这是源代码:
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();
}
}
}
}
回答by Itay Karo
With AtomicInteger
the incrementAndGet()
guaranteed to be atomic.
If you use count++
to get the previous value it is not guaranteed to be atomic.
随着AtomicInteger
该incrementAndGet()
保证是原子。
如果您使用count++
获取先前的值,则不能保证它是原子的。
Something the I missed from your question - and was stated by other answer - static has nothing to do with threading.
我从你的问题中遗漏了一些东西 - 并由其他答案陈述 - 静态与线程无关。
回答by TieDad
"static" make the var to be class level. That means, if you define "static int count" in a class, no matter how many instances you created of the class, all instances use same "count". While AtomicInteger is a normal class, it just add synchronization protection.
“静态”使 var 成为类级别。这意味着,如果您在类中定义“静态整数计数”,则无论您为该类创建了多少个实例,所有实例都使用相同的“计数”。虽然 AtomicInteger 是一个普通的类,但它只是添加了同步保护。
回答by Subhrajyoti Majumder
static int counter
would give you inconsistent result in multithreaded
environment unless you make the counter volatile
or make the increment block synchronized
.
static int counter
multithreaded
除非您制作计数器volatile
或制作增量块,否则会在环境中给您不一致的结果synchronized
。
In case of automic
it gives lock-free
thread-safe
programming on single variables.
在这种情况下,automic
它lock-free
thread-safe
可以对单个变量进行编程。
回答by Vertex
I think there is no gurantee to see on count++
the newest value. count++
must read the value of count
. Another Thread
can have written a new value to count
but stored it's value on the Thread
local cache, i. e. does not flush to main memory. Also your Thread
, that reads count
, has no gurantee to read from the main memory, i. e. refresh from main memory. synchronize
gurantees that.
我认为没有保证可以看到count++
最新的价值。count++
必须读取 的值count
。另一个Thread
可以写入一个新值count
但将它的值存储在Thread
本地缓存中,即不会刷新到主内存。此外,您的Thread
, 读取count
,无法保证从主内存读取,即从主内存刷新。synchronize
保证。
回答by Pankaj
AtomicInteger is to make the get and increment as an atomic process. It can be thought as a Sequencer in Database. It provides utility methods to increment, decrement delta int values.
AtomicInteger 是让 get 和 increment 作为一个原子过程。它可以被认为是数据库中的一个Sequencer。它提供了增加、减少 delta int 值的实用方法。
static int can cause issue if you are getting counter and then processing and then updating it. AtomicInteger does it easily but you can't use it if you have to update the counter based on processing results.
如果您获取计数器然后处理然后更新它,静态 int 可能会导致问题。AtomicInteger 很容易做到,但如果您必须根据处理结果更新计数器,则无法使用它。