多个线程不能同时进入一个同步块吗?

Posted

技术标签:

【中文标题】多个线程不能同时进入一个同步块吗?【英文标题】:Are not multiple threads able to enter a synchronized block at the same time? 【发布时间】:2015-03-02 02:20:07 【问题描述】:

我是 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首先进入同步块(因为只有一个人可以获取monitor-object this的锁并进入同步块) --2 A 调用 this.wait() 并因此释放监视器对象上的锁 this(wait() 调用释放监视器对象 http://tutorials.jenkov.com/java-concurrency/thread-signaling.html#wait-notify 上的锁)但仍保留在同步块内 --3 现在 B 进入同步块(因为 A 已经释放了对监视器对象的锁定) --4 B 调用 this.wait() 并因此释放对监视器对象的锁定 this (wait() 调用释放对监视器对象的锁定) --5 此时线程 C 调用 unlock() 即设置 isLocked 为 false 并调用 this.notify() --6 现在A和B之一出来wait(),然后出来while循环,设置isLocked为true --7 循环继续

那么在--3中,A和B同时在一个同步块中,一次只允许一个线程在一个同步块中是不是违反了基本的多线程原则?

请澄清我的疑问。

【问题讨论】:

【参考方案1】:

如果线程重新获得了它正在等待的对象上的锁,它只能从 wait() 方法返回。在您的场景中,A 和 B 将竞争获得锁,只有其中一个会获得它,而另一个会一直等待直到再次释放锁。

来自the javadoc(强调我的):

当前线程必须拥有该对象的监视器。线程释放此监视器的所有权并等待,直到另一个线程通过调用 notify 方法或 notifyAll 方法通知在此对象的监视器上等待的线程唤醒。 然后线程等待,直到它可以重新获得监视器的所有权并恢复执行。

【讨论】:

以上是关于多个线程不能同时进入一个同步块吗?的主要内容,如果未能解决你的问题,请参考以下文章

两个线程同时执行同步块

Java 多线程同步的五种方法

Java学习笔记---多线程同步的五种方法

同步-同步锁-死锁-线程交互-线程综合示例

线程同步测试

Java学习--线程