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.
CodePudding user response:
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
acquirescount
lock (Notice that thecount object
is locked), at this pointthread r2
is blocked.r1
invokescount
, a newInteger
object is created. Thecount
reference is then directed to the new object. Andr1
release lock.(This lock refers to the previous Integer object).r2
which had been blocked acquires lock.r1
also acquires the lock becausecount
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");
}
}