2

In the below example, lock is obtained on instance variable employee (not on this), but still Threads of TestClass1 are getting locked while entering synchronized block. Any advice why is this behaviour. As far as my understanding it should get locked if its synchronization is on this.

public class TestClass{
  public static void main(String args[]){
    TestClass1 obj = new TestClass1();
    Thread t1 = new Thread(obj, "T1");
    Thread t2 = new Thread(obj, "T2");
    t1.start();
    t2.start();
  }
}

class TestClass1 implements Runnable{

Employee employee = new Employee();

public void myMethod () {
    synchronized (employee) {
        try {
            Thread.sleep(4000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public void myOtherMethod() {
    synchronized (employee) {
        try {
            Thread.sleep(4000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

@Override
public void run() {
    myMethod();
    myOtherMethod();
}
}
AlexR
  • 114,158
  • 16
  • 130
  • 208
Sameer
  • 425
  • 1
  • 7
  • 15

4 Answers4

5

You are using the same TestClass1 instance for both threads, therefore they are using the same Employee instance to lock on.

To get them to use different locks, you need to do:

Thread t1 = new Thread(new TestClass1(), "T1");
Thread t2 = new Thread(new TestClass1(), "T2");
Keppil
  • 45,603
  • 8
  • 97
  • 119
  • Exactly what I was gonna say :) – An SO User May 26 '13 at 11:42
  • Actually what I have understood is synchronized(this) will lock on threads working for same object (as per above example). But in my example I have kept synchronized(instance variable), so how does threads are getting locked on instance variable... – Sameer May 26 '13 at 11:44
  • `synchronized(this)` is discouraged :) – An SO User May 26 '13 at 11:45
  • @Sameer wait, I will explain with a simple example – An SO User May 26 '13 at 11:45
  • @Sameer `synchronized(this)` is the same as `synchronized(employee)` in your case as `employee` has the same scope as `this`. – Boris the Spider May 26 '13 at 11:46
  • @Keppil, with your suggested code, both the threads for the class TestClass1 are not getting locked (as expected as both threads are assigned different instances of TestClass1)..They are rather independent (which I have understood clearly). – Sameer May 26 '13 at 11:56
  • @LittleChild Any particular reason why synchronized(this) is discouraged and synchornized(instance var) is preferred.... ? – Sameer May 26 '13 at 11:57
  • http://stackoverflow.com/questions/442564/avoid-synchronizedthis-in-java have a look at the answer by `cletus` – An SO User May 26 '13 at 12:05
2

Both threads use the same instance of TestClass1. So internally they share the same employee instance. To avoid this create a new instance for each Thread.

Robe Elckers
  • 967
  • 1
  • 6
  • 19
2

You are using the same object (employee) for your synchronization. It means that indeed of one thread entered the synchronized block other thread will be locked until the first frees the lock. It does not matter whether you are using this or any other object. What does matter is that this is the same object.

This is the purpose of synchronization. If access to specific object should be synchronized because the data may be inconsistent if 2 or more threads use this data simultaneously we use synchronization.

AlexR
  • 114,158
  • 16
  • 130
  • 208
  • Same object used to create threads. It is just a duplicate thread he is making :) It is bound to get locked – An SO User May 26 '13 at 11:44
0

What you are doing is creating a Runnbable object and making two Thread object out of it. Assigning two different names to the threads does not make them two threads and conversely, assigning same name to two threads does not make them one thread .

Basically, you are creating a duplicate thread with the same resources.

So, your first thread locks onto the employee and the second thread (which in reality is the same Runnable as the first that obtained the lock) requests a lock on employee. So, it gets blocked.

What is happening is that the Runnable is requesting a lock on itself.

Just do as Keppil suggested:

Thread t1 = new Thread(new TestClass1(), "T1");
Thread t2 = new Thread(new TestClass1(), "T2");
An SO User
  • 24,612
  • 35
  • 133
  • 221