2

在我的程序中,我有一个线程将供应变量增加 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;
    }
}
4

6 回答 6

4

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

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

请注意,您还需要对从/向“供应”变量读取/写入的其他方法使用同步。

于 2013-04-30T23:12:17.860 回答
1

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

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

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

于 2013-04-30T23:38:39.797 回答
1
int temp = supply + 2;
if (temp > MAX)
  temp = MAX;
supply = temp;

不过,这仍然不是线程安全的。您应该研究锁和同步。

于 2013-04-30T23:10:11.230 回答
1

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

synchronized(this) {
     supply = supply+2
 }
于 2013-04-30T23:16:43.323 回答
1

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

于 2013-05-01T00:10:58.327 回答
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);
    }
}
于 2013-04-30T23:44:12.860 回答