我在同步块上找到的几乎所有资源都使用 this 或类的成员作为锁定对象。我有兴趣找出当锁对象是另一个类的(静态)成员时,为什么我不能使同步块工作。这是我的代码来说明问题:
public class Test {
public static void main(String[] args) {
Thread thread1 = new FirstThread();
Thread thread2 = new SecondThread();
thread1.start();
thread2.start();
}
}
class FirstThread extends Thread {
@Override
public void run() {
synchronized (Lock.lock) {
System.out.println("First thread entered block");
try {
Lock.lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("First thread exited block");
}
}
class SecondThread extends Thread {
@Override
public void run() {
try {
Thread.sleep(1000); //just making sure second thread enters synch block after first thread
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (Lock.lock) {
System.out.println("Second thread entered block");
Lock.lock.notifyAll();
}
System.out.println("Second thread exited block");
}
}
class Lock {
public static Object lock = new Object();
}
我的理解是第二个线程在第一个线程退出之前不应该进入同步块,因为它们在同一个对象上同步。因此我期待程序在#34;第一个线程进入块"之后挂起(死锁?),因为第二个线程无法进入块并且第一个线程将被卡住等待通知。但我得到了以下输出:
First thread entered block
Second thread entered block
Second thread exited block
First thread exited block
显然,第二个线程在第一个线程离开它之前进入同步块。有人能解释我错过的东西吗? 我认为同步块的目的是为了防止这一点。是因为lock对象是另一个类的成员吗?
答案 0 :(得分:3)
第一个线程Lock.lock.wait()放弃对同步对象的锁定,这样其他线程就可以进入关键路径并唤醒服务员。
请注意,sleep()不会。
答案 1 :(得分:2)
线程释放此监视器的所有权并等待,直到另一个线程通过调用notify方法或notifyAll方法通知等待此对象监视器的线程唤醒。
如果不是这种情况,等待将系统地导致死锁,因为没有线程能够进入调用notify()
或notifyAll()
所需的同步部分,等待并通知完全无用
答案 2 :(得分:1)
当您拨打锁定时,wait即可释放此监视器的所有权"。这允许线程2进入同步块。