package sync.block.lock.on.thisObj;
public class Counter {
int count = 0;
public void increment() {
synchronized (this) {
count++; // STATEMENT 1
//System.out.println(count);
}
System.out.println(count+" increment"); // STATEMENT 2
//System.out.println(count);
}
public void decrement() {
synchronized (this) {
count--; // STATEMENT 3
//System.out.println(count);
}
System.out.println(count+" decrement"); // STATEMENT 4
//System.out.println(count);
}
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
counter.decrement();
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
counter.increment();
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Main Thread: "+counter.count);
}
}
Following is the result:
0 increment
1 increment
2 increment
3 increment
4 increment
5 increment
6 increment
0 decrement // How this entry and all the following entries?
6 decrement
5 decrement
4 decrement
3 decrement
2 decrement
1 decrement
7 increment
1 increment
2 increment
0 decrement
1 decrement
0 decrement
Main Thread: 0
I agree for the expected result, sysout
should be inside synchronized
block.
But what sequence of execution might have caused to produce the entry 0 decrement
and all its subsequent entries?
My expected sequence of exection:
STATEMENT 1 - increments 1
STATEMENT 3 - decrements 1
STATEMENT 2 - 0 increment printed
STATEMENT 1
--> possibility for STATEMENT 3 to be executed.But it didn't.Because if it had,next statement would have printed 0.
STATEMENT 2 - 1 increment
STATEMENT 1
--> possibility for STATEMENT 3 to be executed.But it didn't.Because if it had,next statement would have printed 1.
STATEMENT 2 - 2 increment
STATEMENT 1
STATEMENT 2 - 3 increment
STATEMENT 1
STATEMENT 2 - 4 increment
STATEMENT 1
STATEMENT 2 - 5 increment
STATEMENT 1
STATEMENT 2 - 6 increment (at this point,count is 6)
STATEMENT 4 - 0 decrement (it must be 6 , or it must be 7 if STATEMENT 1 is executed before this statment. Why 0??)
EDIT: My understanding based on the "happens-before" relationship of lock release and subsequent acquisition of the same lock :
1) t1 increment acquires lock, count++ (count = 1), releases lock.
2) t2 decrement acquires lock,sees count as 1 since it acquired the same lock and now happens-before relationship is established (memory state at the time of release is visible at the time acquiring the same lock), count-- (count = 0), releases lock.
3) t1 increment prints count (count = 0 made by t2 decrement need not necessarily be visible to t1 since t1 has not yet acquired the lock released by t2 but it may be visible). Here it is visible and prints 0.
4) t1 increment acquires lock and increments and this goes on until count = 6 is printed in t1.
5) t2 decrement prints count (count = 6 made by t1 may be not be visible since t2 has not acquired the lock released by t1). Here it is not visible. At this point value of
count
visible is 0 (from its previous decrement in step (2))....