如何实现一个可以使用Java安全递增的多线程变量?

时间:2013-04-30 23:08:10

标签: java multithreading

在我的程序中,我有一个线程将供应变量递增2,然后另一个线程从供应类中获取随机数量的供应。供应类最多只能存储5个值,并且由于睡眠和供应请求是随机的,因此供应计数可以超过其最大限制。

我要确保的是它没有超过这个限制。

有更好的方法吗?

(伪代码)

  1. 按2增加供应
  2. 如果供应量超过最大值,则将供应分配给最大值
  3. 以下是代码:

    private int MAX = 5;
    private int supply = 0;
    public void run()
    {
        while(true) {
          supply = supply + 2;
          if(supply > MAX) 
              supply = MAX;
        }
    }
    

6 个答案:

答案 0 :(得分:4)

您可以使用公共同步的incSupply()方法来增加供应变量:

public synchronized void incSupply()
{
    // Code borrowed from Jean-Bernard Pellerin.
    int temp = supply + 2;
    if (temp > MAX)
        temp = MAX;
    supply = temp;
}

请注意,对于从'supply'变量读取/写入的其他方法,您还需要使用synchronized。

答案 1 :(得分:1)

int temp = supply + 2;
if (temp > MAX)
  temp = MAX;
supply = temp;

但这仍然不是线程安全的。你应该研究锁和同步。

答案 2 :(得分:1)

如果你有多个线程,你应该声明你的公共资源,(意味着其他线程对该变量执行命令)在你的情况下,我猜是供应,如同步。并使用细粒度同步

synchronized(this) {
     supply = supply+2
 }

答案 3 :(得分:1)

我不完全理解你问题的这一部分:and the other thread takes a random number of supply from the supply class。这是否意味着消费线程可以从供应类中获取随机数量的值,或者是一个随机数的值?

在任何情况下,您都有一个需要互斥访问的资源,因此您需要确保只有一个线程可以修改它。在java中,这可以通过在被修改的实例上请求内部锁来轻松完成,只有一个线程可以在任何给定时间保持此锁。现在,当一个线程遇到一个synchronized块时(根据Stelsavva的例子),它会自动尝试在this代表的任何实例上获取内部锁,并保持它直到块结束。如果任何其他线程遇到该块,而另一个线程持有该锁,则它将等待,直到另一个线程释放该锁。

因此,块的执行是同步的,你不会遇到交错问题。

答案 4 :(得分:1)

使用具有五个许可证的Semaphore。有点违反直觉,我认为许可证代表了存储供应的许可,因此第一个线程需要获得存储供应品的许可证。当第二个线程获取耗材时,它会释放许多许可证。

答案 5 :(得分:0)

最简单的解决方案是使用AtomicInteger而不会遇到同步增量的麻烦:

private int MAX = 5;
private AtomicInteger supply = new AtomicInteger(0);
public void run()
{
    while(true) {
      if(supply.addAndGet(2) > MAX) 
          supply.set(MAX);
    }
}