user2273278
user2273278

Reputation: 1315

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

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)

  1. increment supply by 2
  2. if supply is more than max then assign supply to max

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

Answers (6)

Stephan
Stephan

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

flup
flup

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

JustDanyul
JustDanyul

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

Jonny Dee
Jonny Dee

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

Stelios Savva
Stelios Savva

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

Jean-Bernard Pellerin
Jean-Bernard Pellerin

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

Related Questions