How to solve multiple thread static variable incrementation?(如何解决多线程静态变量递增?)
问题描述
所以我的问题本质上是,即使我使用静态的可变int变量进行递增,我的一些数据也不是唯一的,这将是我的目标(我为我的元素编号)。
public class Producer implements Runnable{
private String str;
private Fifo f;
private int i;
private static volatile int n=0;
public Producer(String str,int i,Fifo f) ....
public void run() {
try {
this.go();
} catch (InterruptedException e) {
;
}
}
void go() throws InterruptedException {
while(true) {
Thread.sleep(i);
int l=n++;
String k=str+" "+l+" ";
f.put(k);
System.out.println("produced "+str+" "+l+" "+System.currentTimeMillis()%100000);
}
}
}
我的问题出在go()函数中。我给我的元素编号,我有多个生产者对象作为独立的线程运行,但有时它们表现得好像不知道n是否已经更新,所以我得到了相同的索引。 有什么主意吗? (我知道可能是什么问题,但我不知道如何解决它。)
推荐答案
似乎对volatile
的作用存在误解。关键字volatile
引入了写入和读取之间的先发制人语义。但是,它不会使多个操作成为原子操作。
如果我们手写n++
";的语义(请不要这样做,它仅用于解释目的),它将如下所示:
final int result;
n = (result = n) + 1;
Ideone demo
查看此代码,我们看到我们必须:
- 读取
n
, 的值
- 将其存储在某个临时变量中
result
, - 递增
1
, - 将(递增的)值写回
n
所以我们有多个操作。如果这些操作由不同的线程多次并行执行,那么我们可以看到导致数据不一致的多种可能的交织。例如,两个线程都可以读取n
的(当前)值。两者都会将值加一,并且都会将新值写回n
。这意味着有两个线程执行了";增量";,但n
的值只增加了1
,而不是2
。
AtomicInteger
--来避免这个问题。用法如下所示:
public class Producer implements Runnable {
...
private static final AtomicInteger n = new AtomicInteger(0);
...
void go() throws InterruptedException {
while(true) {
...
int l = n.getAndIncrement();
...
}
}
}
这篇关于如何解决多线程静态变量递增?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何解决多线程静态变量递增?
基础教程推荐
- 由于对所需库 rt.jar 的限制,对类的访问限制? 2022-01-01
- 如何在不安装整个 WTP 包的情况下将 Tomcat 8 添加到 Eclipse Kepler 2022-01-01
- 如何使用 Stream 在集合中拆分奇数和偶数以及两者的总和 2022-01-01
- 在螺旋中写一个字符串 2022-01-01
- 如何强制对超级方法进行多态调用? 2022-01-01
- 如何使用 Eclipse 检查调试符号状态? 2022-01-01
- Java 中保存最后 N 个元素的大小受限队列 2022-01-01
- 首次使用 Hadoop,MapReduce Job 不运行 Reduce Phase 2022-01-01
- 如何对 HashSet 进行排序? 2022-01-01
- Spring Boot Freemarker从2.2.0升级失败 2022-01-01