如何解决多线程静态变量递增? [英] How to solve multiple thread static variable incrementation?

查看:95
本文介绍了如何解决多线程静态变量递增?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我的问题本质上是,即使我使用静态的可变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

查看此代码,我们看到我们必须:

  1. 读取n
  2. 的值
  3. 将其存储在某个临时变量中result
  4. 递增1
  5. 将(递增的)值写回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();
                ...
        }
    }

}

这篇关于如何解决多线程静态变量递增?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆