繁体   English   中英

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

[英]How do I implement a multi-threaded variable that I can safely increment using Java?

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

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

有一个更好的方法吗?

(伪代码)

  1. 增加供应2
  2. 如果供应量超过最大值,则将供应量分配给最大值

这是代码:

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

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

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

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

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

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

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

synchronized(this) {
     supply = supply+2
 }

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM