Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Increment an int using threads

I have two threads and I want to increment an int variable while it is less than a certain value. My program does that but two different threads do not increment the value separately.
If one and two are two threads, I want the output to be like this

one 1  
two 2  
one 3  
two 4  
one 5  
two 6  
one 7  
two 8...  

Here is my program:

class IncTo100Demo implements Runnable {
    public volatile int count = 0;

    public void run() {
        Thread current = Thread.currentThread();
        try {
            while(count < 21) {
                System.out.println(current.getName() + " count = " + count++);
                current.sleep(1000);
            }
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Thread one = new Thread(new IncTo100Demo(), "one");
        Thread two = new Thread(new IncTo100Demo(), "two");

        try {
            one.start();
            two.start();
            System.out.println("one alive? " + one.isAlive());
            one.join();
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }
}  

and its output is:

one alive? true
two count = 0
one count = 0
two count = 1
one count = 1
two count = 2
one count = 2
two count = 3
one count = 3
two count = 4
one count = 4
two count = 5
one count = 5
two count = 6
one count = 6
two count = 7
one count = 7
two count = 8
one count = 8
two count = 9  

How can I make these threads update the variable individually so that the output can look like what I want it to?

like image 360
strider14 Avatar asked May 22 '16 05:05

strider14


People also ask

Can you increment by 2 in Java?

Can I increment by 2 in a for loop in Java? If you want to increment or decrement a variable by an amount other than 1 , you can use += and -= . For example, i += 2 increments i by 2 : int i = 2; while (i <= 8) { System.

Is interlocked increment thread-safe?

The Interlocked class provides a number of static methods that perform atomic operations. These can generally be regarded as thread-safe.

Is increment operator thread-safe C#?

++ is not defined as thread-safe.

How do you add increments in Java?

There are two ways to use the increment operator; prefix and postfix increment. The prefix increment looks like ++variablename; while the postfix increment looks like variablename++; . Both of these operations add one to the value in the variable.


1 Answers

count is an instance variable of class IncTo100Demo. Each of your threads uses its own instance of that class, and therefore works with its own copy of that variable. That's why they update the values independently. To make the threads share, you must either have them use the same instance of your class, or you must make count static.

Furthermore, once the two threads are accessing the same count variable, having that variable be volatile is not sufficient to guarantee the behavior you want. You are fairly likely to see that behavior, but it would still be possible for one thread to fail to see the other's updates to the variable. This is because evaluating the expression count++ and applying its side effect is not atomic. It is possible, therefore, that both threads read the same value of count (i.e. before either one writes an updated value). In that case, both will compute the same updated value, and both will write it. The result would look similar to the erroneous output you present, though it would be likely to be (very) occasional, not consistent.

To avoid that problem, you need to synchronize access to count (which then does not need also to be volatile). You cannot do that by synchronizing the run() method, however, for that would make the method synchronize using the monitor of the object on which run() is invoked. If your threads use the same IncTo100Demo instance then that will prevent any concurrency, and if they do not then that will not be effective.

Instead, use a synchronized block inside run(). If the two threads share the same IncTo100Demo instance (which I recommend) then you can synchronize on that instance:

synchronized (this) {
    // ... read and manipulate 'count'
}

Otherwise, you'll need to create another object shared between the the threads, and synchronize on that. Be careful that all accesses to count on each loop iteration are within the same synchronized block (including the count < 21 test), but that the sleep() is outside it. You want the scope of the synchronization to be as narrow as possible.

Since this appears to be an educational exercise, I leave the details for you to work out, but I'll give you this hint: you probably need to re-structure your loop.

like image 196
John Bollinger Avatar answered Sep 30 '22 05:09

John Bollinger