在我的程序中,我有一个线程将供应变量递增2,然后另一个线程从供应类中获取随机数量的供应。供应类最多只能存储5个值,并且由于睡眠和供应请求是随机的,因此供应计数可以超过其最大限制。
我要确保的是它没有超过这个限制。
有更好的方法吗?
(伪代码)
以下是代码:
private int MAX = 5;
private int supply = 0;
public void run()
{
while(true) {
supply = supply + 2;
if(supply > MAX)
supply = MAX;
}
}
答案 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);
}
}