Reputation: 12452
private Object x = new Object();
public void doA() {
synchronized(x){
x = new Object();
//do something
}
}
public void doB() {
synchronized(x) {
//do something
}
}
lets say doA()
and doB()
was called simultaneously but doA()
is proceeding first. so B will be blocked until doA()
is completed
is this true even if doA()
modifies x in the x = new x
call? or after this line x = new x
in doA()
doB()
will no longer be blocked because x
has changed?
Upvotes: 3
Views: 597
Reputation: 19320
My own curiosity got the best of me and I wrote this test to verify what happens. The lock is still held on the original reference and does not change.
import java.io.IOException;
import java.util.StringTokenizer;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
public class Test {
private static Object x = new Object();
public static void main(String[] args) throws Exception {
Test a = new Test();
Test b = new Test();
Thread t = new Thread(a.new MyRunnable());
t.start();
Thread.sleep(100);
b.doB();
}
public void doB() {
System.out.println("here b");
synchronized (x) {
System.out.println("here sync b");
}
System.out.println("here done sync b");
}
public class MyRunnable implements Runnable {
public MyRunnable() {
}
public void run() {
System.out.println("here a");
synchronized (x) {
System.out.println("here sync a");
try {
Thread.sleep(5000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
x = new Object();
System.out.println("here new object a");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("here after sleep a");
}
System.out.println("here done sync a");
}
}
}
Output is below. Clearly the lock is still held on to the original reference even after reassignment.
here a
here sync a
here b
here new object a
here after sleep a
here done sync a
here sync b
here done sync b
Upvotes: 2
Reputation: 319
What happens would really depend on how quickly doA()
gets run:
If doA()
changes the value of x
before doB()
reaches its synchronized block, then doB()
will lock on the new object that doA()
created.
If doB()
is speedy and the synchronized(x)
part gets evaluated before doA()
can change the value of x
, then doB()
will have to wait until doA()
's synchronized
block finishes.
Whenever Java gets to the synchronized(x)
code in either method, it evaluates the variable x
, and that variable gives Java an object. So Java then tries to lock on that object, and stay locked on that object. Or, if there's already a lock on that object, it will wait for the lock to go away. (Whenever Java reaches the synchronized(x)
code, it takes the value of the variable and ignores forgets the variable itself, so you can change the variable as you please afterwards, but locking and lock checking still happen on the variable's previous value.)
Upvotes: 4
Reputation: 1436
I think the doA() method will still hold the lock on old "x". Other thread waiting for lock on "x" won't be notified unless the thread holding is finished processing synchronized block. Once synchronized block is completed, threads will fight to acquire lock on new instance of x.
Upvotes: 1