Reputation: 3
public class SyncBlockIssue {
public static void main(String[] args) {
Thread r1= new Multi();
Thread t1= new Thread(r1);
Thread t2= new Thread(r1);
t1.start();
t2.start();
}
}
class Multi extends Thread
{
Integer count =new Integer(0);
@Override
public void run() {
for(int i=0;i<100000;i++)
{
synchronized (count) {
//synchronized (this) { //working fine with this
count++;
}
}
System.out.println(Thread.currentThread().getName() + " "+count);
}
}
Above code is printing 2 million from 2nd thread, no matter how many times i run when acquire lock on 'this', but where as printing arbitrarily count, when acquired lock 'count' object. could someone explain the difference.
Upvotes: 0
Views: 81
Reputation: 1877
Here's my guess, since I can't use comments to type so many words.
Integer
objects are immutable:
/**
* The value of the {@code Integer}.
*
* @serial
*/
private final int value;
/**
* Constructs a newly allocated {@code Integer} object that
* represents the specified {@code int} value.
*
* @param value the value to be represented by the
* {@code Integer} object.
*/
public Integer(int value) {
this.value = value;
}
So, when you do count++
, a new Integer
object will be created. The count
reference is then directed to the new object.
Assume the following flow:
Thread r1
acquires count
lock (Notice that the count object
is locked), at this point thread r2
is blocked.
r1
invokes count++
, a new Integer
object is created. The count
reference is then directed to the new object. And r1
release lock.(This lock refers to the previous Integer object).
r2
which had been blocked acquires lock.
r1
also acquires the lock because count
has already pointed to a new object.
Both threads execute count++
: problem arises.
The following code proves that both threads are holding the "lock" at the same time
for(int i=0; i<2; i++)
{
synchronized (count) {
System.out.println(Thread.currentThread().getName() + "get lock");
count++;
if (i == 1) {
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "release lock");
}
}
Upvotes: 2