在下面的示例中,在实例变量employee上获取锁定(不在此上),但在进入synchronized块时,仍然会锁定TestClass1的Threads。任何建议为什么这种行为。据我所知,如果它同步就会被锁定。
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();
}
}
答案 0 :(得分:5)
您对两个线程使用相同的TestClass1
实例,因此它们使用相同的Employee
实例来锁定。
要让他们使用不同的锁,您需要执行以下操作:
Thread t1 = new Thread(new TestClass1(), "T1");
Thread t2 = new Thread(new TestClass1(), "T2");
答案 1 :(得分:2)
两个线程都使用TestClass1
的相同实例。所以内部他们共享相同的employee
实例。为避免这种情况,请为每个Thread
创建一个新实例。
答案 2 :(得分:2)
您正在使用相同的对象(employee
)进行同步。这意味着确实有一个线程进入同步块,其他线程将被锁定,直到第一个释放锁。无论您使用this
还是其他任何对象都无关紧要。重要的是这是同一个对象。
这是同步的目的。如果应同步对特定对象的访问,因为如果两个或多个线程同时使用此数据,则数据可能不一致,我们使用同步。
答案 3 :(得分:0)
您正在做的是创建一个Runnbable
对象并从中创建两个Thread
对象。为线程分配两个不同的名称不会使它们成为两个线程,相反,为两个线程分配相同的名称并不会使它们成为一个线程。
基本上,您正在创建具有相同资源的重复线程。
因此,您的第一个线程锁定到employee
,第二个线程(实际上与获得锁定的第一个线程相同Runnable
)请求锁定employee
。所以,它被阻止了。
正在发生的事情是Runnable
正在请求锁定自身。
就像Keppil建议的那样:
Thread t1 = new Thread(new TestClass1(), "T1");
Thread t2 = new Thread(new TestClass1(), "T2");