0

Look at the output, despite making the method synchronized, the output is not ordered. Since both threads increment the same object 'job' on the heap, whichever thread prints the line, the result should be an increased value. But why is it printing in disorderly manner?

class TestSync implements Runnable{
  private int balance;

  public void run(){
    for(int i=0; i<50; i++) {
      increment();   
    System.out.println("balance is "+balance);
    }
  }
  public synchronized void increment(){
   balance++;     
  }
}


public class TestSyncTest {

  public static void main(String[] args){
    TestSync job = new TestSync();
    Thread a = new Thread(job);
    Thread b = new Thread(job);
    a.start();
    b.start();
  }
}

Output:

balance is 2
balance is 3
balance is 4
balance is 5
balance is 6
balance is 7
balance is 8
balance is 9
balance is 10
balance is 11
balance is 12
balance is 13
balance is 14
balance is 15
balance is 16
balance is 17
balance is 18
balance is 19
balance is 20
balance is 21
balance is 22
balance is 23
balance is 24
balance is 2
balance is 25
balance is 27
balance is 28
balance is 29
balance is 26
balance is 30
balance is 32
balance is 33
balance is 34
balance is 35
balance is 36
balance is 37
balance is 31
balance is 38
balance is 40
balance is 41
balance is 42
balance is 43
balance is 44
balance is 39
balance is 46
balance is 47
balance is 45
balance is 49
balance is 48
balance is 50
balance is 52
balance is 51
balance is 53
balance is 55
balance is 54
balance is 56
balance is 58
balance is 59
balance is 60
balance is 57
balance is 61
balance is 62
balance is 63
balance is 64
balance is 65
balance is 66
balance is 67
balance is 68
balance is 69
balance is 70
balance is 71
balance is 72
balance is 73
balance is 74
balance is 75
balance is 76
balance is 77
balance is 78
balance is 79
balance is 80
balance is 81
balance is 82
balance is 83
balance is 84
balance is 85
balance is 86
balance is 87
balance is 88
balance is 89
balance is 90
balance is 91
balance is 92
balance is 93
balance is 94
balance is 95
balance is 96
balance is 97
balance is 98
balance is 99
balance is 100
2

3 Answers 3

2

The only thing that is synchronized is the incrementation. The reading of the variable before printing it is not, and the printing itself is synchronized on another lock. So you could get

  • thread 1: increment
  • thread 2: increment
  • thread 1: read and print
  • thread 2: read and print

BTW, the balance is shared state, and all the accesses, including reading the value of the variable, should be synchronized on the same lock.

Change the code to

class TestSync implements Runnable{
    private int balance;

    public void run(){
        for(int i = 0; i < 50; i++) {
            incrementAndPrint();   
        }
    }

    public synchronized void incrementAndPrint(){
        balance++;     
        System.out.println("balance is "+balance);
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

The println is also synchronized, but not using the same lock.
So the statement System.out.println("balance is "+balance); consists of 2 steps: 1. read the value in balance and 2. print it. One thread could've read the value but was freezed before it could print it and when it is released again, it prints the value it read before it was freezed. Is that right ?
It's actually much more atomic steps than that: read the value, then concatenate the value to a string, which itself needs to create a new har array, copy every char of the original string to the new array, transform the integer into a string, etc. Between each of these atomic steps, the thread might be paused by the scheduler to execute another one. But, even if the whole thing was a single atomic operation, since it's done outside of the synchronized block, thread 2 can increment before thread1 prints.
0

synchronized only protects the block synchronized. It is a common mistake to assume that if you sprinkle a little thread safe around your program it will do what you want. Thread safety is a like a chain of operations, if any is not synchronized, you code can execute in any order.

But why is it printing in disorderly manner?

The purpose of thread is to run independent tasks concurrently. As such you should expect there to be time when one or the other thread executes faster than the other one.

The real question should be; why is it orderly at all.

This is most likely due to one thread starting before the other. When one thread is running, and the other hasn't started yet, the output is "orderly" however once both threads are running you can see race conditions.

Comments

0

You have 2 threads printing a counter, the app is working ok, as you can see every thread is printing in the console as soon as the want to give the counter value, the look like mixed up because there is no easy way to format or identify what value is comming from which thread...

add a name to a every thread and print the name too, so you can see the origin of the data...

Thread a = new Thread(job, "t1");
Thread b = new Thread(job, "t2");

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.