我是Java的新手,在了解java中的多线程时遇到了这个链接:http://tutorials.jenkov.com/java-concurrency/slipped-conditions.html。
在本教程中,以下代码被称为避免条件下滑的良好做法:
public class Lock {
private boolean isLocked = true;
public void lock(){
synchronized(this){
while(isLocked){
try{
this.wait();
} catch(InterruptedException e){
//do nothing, keep waiting
}
}
isLocked = true;
}
}
public synchronized void unlock(){
isLocked = false;
this.notify();
}
}
我怀疑是两个线程A& B同时调用lock()并且isLocked为true,即其他一些线程C已经锁定了。现在:
- 1 A首先进入同步块(因为只有一个可以获得对此监视对象的锁定并进入同步块) --2 A调用this.wait()并释放对monitor-object的锁定(wait()调用释放monitor-object http://tutorials.jenkov.com/java-concurrency/thread-signaling.html#wait-notify上的锁)但保持在synchronized块内 --3现在B进入同步块(因为A释放了对monitor-object的锁定) --4 B调用this.wait()并释放对monitor-object的锁定(wait()调用释放monitor-object上的锁) --5此时线程C调用unlock(),即将isLocked设置为false并调用this.notify() --6现在A和B中的一个出来wait(),然后退出while循环并将isLocked设置为true - 7并且循环继续
所以在-3中,A和B同时在同步块内,是不是违反了基本的多线程原则,一次只允许在同步块内有一个线程?
请澄清我的疑问。
答案 0 :(得分:4)
如果一个线程重新获取它正在等待的对象的锁定,它只能从wait()方法返回。在你的场景中,A和B将竞争获得锁定,只有其中一个获得它,而另一个将继续等待直到锁定再次释放。
来自the javadoc(强调我的):
当前线程必须拥有此对象的监视器。该线程释放该监视器的所有权并等待,直到另一个线程通过调用notify方法或notifyAll方法通知等待该对象监视器的线程唤醒。 线程然后等待,直到它可以重新获得监视器的所有权并继续执行。