我是新接触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为真,即锁已被某个其他线程C占用。现在:
--1 A首先进入同步块(因为只有一个人可以获得对监视器对象http://tutorials.jenkov.com/java-concurrency/thread-signaling.html#wait-notify)的锁定并进入同步块)--2 A调用这个.Wait(),因此释放对监视器对象的锁定。这个(Wait()调用释放对监视器对象Wait的锁定,但保持在同步块内-3现在B进入同步块(因为A已经释放了对监视对象的锁定)--4 B调用这个。Wait(),依此类推释放监视器对象上的锁这个(Wait()调用释放监视器对象上的锁)--5此时线程C调用unlock(),即将isLocked设置为False并调用this.tify()--6现在A和B中的一个出来等待(),然后从While循环中退出,并将isLocked设置为真--7,循环继续
因此,在--3中,A和B同时位于一个同步块中,这是否违反了一个同步块中一次只允许一个线程的基本多线程原则?
请澄清我的疑问。
2条答案
按热度按时间dxpyg8gm1#
线程只有在重新获取它正在等待的对象上的锁时,才能从Wait()方法返回。在您的场景中,A和B将竞争获得锁,其中只有一个将获得锁,而另一个将继续等待,直到锁再次被释放。
来自javadoc(重点是我的):
当前线程必须拥有此对象的监视器。该线程释放该监视器的所有权并等待,直到另一个线程通过调用Notify方法或NotifyAll方法通知等待该对象的监视器的线程唤醒。线程然后等待,直到它可以重新获得监视器的所有权并恢复执行。
gfttwv5a2#
我也有同样的问题,@随机性编译器。
一旦可能有多个线程进入受同一对象监视器锁保护的同步块(或方法),则关键字同步的目的就失效了(例如。代码块中可以有多个线程修改共享数据,尽管只有一个线程占用了CPU)。