Reputation: 1315
In my program I have one thread incrementing a supply variable by 2, then another thread takes a random number of supply from a supply class. The supply class can only store up to 5 values and because the sleep and supply requests are random, the supply count can increment over it's max limit.
What I'm trying to make sure is that it doesn't go over that limit.
Is there a better way to do this?
(pseudocode)
Here is the code:
private int MAX = 5;
private int supply = 0;
public void run()
{
while(true) {
supply = supply + 2;
if(supply > MAX)
supply = MAX;
}
}
Upvotes: 2
Views: 282
Reputation: 8090
The simplest solution is to use AtomicInteger without going throughout the trouble of synchronizing the increment:
private int MAX = 5;
private AtomicInteger supply = new AtomicInteger(0);
public void run()
{
while(true) {
if(supply.addAndGet(2) > MAX)
supply.set(MAX);
}
}
Upvotes: 0
Reputation: 27104
Use a Semaphore with five permits. Somewhat counterintuitively, I think the permit would represent the permission to store a supply, so the first thread would need to acquire permits to store the supplies. When the second thread takes supplies, it releases this many permits.
Upvotes: 1
Reputation: 14044
I dont entirely understand this part of your question: and the other thread takes a random number of supply from the supply class
. Does this mean the consuming thread can take a random number of values from the supply class, or a value which is a random number?
In any case, you have a resource which requires mutually exclusive access, so you need to ensure that only one thread can modify it. In java, this is easily done by requesting a intrinsic lock on the instance being modified, only one thread can hold this lock at any given time. Now, when a thread encounters a synchronized
block (as per Stelsavva's example) it automatically will try and obtain the intrinsic lock on whichever instance this
represents, and hold it until the end of the block. If any other thread encounters the block, while another thread is holding the lock, it will wait until the lock is released by the other thread.
Hence, the execution is of the block is synchronised and you wont have problems with interleaving.
Upvotes: 1
Reputation: 849
You could use a public synchronized incSupply() method which is used to increment the supply variable:
public synchronized void incSupply()
{
// Code borrowed from Jean-Bernard Pellerin.
int temp = supply + 2;
if (temp > MAX)
temp = MAX;
supply = temp;
}
Note that you need to use synchronized also for other methods that read/write from/to the 'supply' variable.
Upvotes: 4
Reputation: 832
If you have more than one thread you should declare your common resource,(meaning other threads execute commands on that variable) in your case i guess would be the supply, as synchronized. and use fine-grained synchronization
synchronized(this) {
supply = supply+2
}
Upvotes: 1
Reputation: 12670
int temp = supply + 2;
if (temp > MAX)
temp = MAX;
supply = temp;
This is still not thread-safe though. You should look into locks and synchronization.
Upvotes: 1