调用notify()后,锁真正释放到什么时候

时间:2018-10-14 11:34:07

标签: java multithreading synchronized

我有经过检查的代码,我只想知道我的理解是正确的。我有以下两个课程

public class WaitCheckWaiter implements Runnable
{

WaitCheck wc;

public WaitCheckWaiter( WaitCheck wc )
{
    this.wc = wc;
}

@Override
public void run()
{
    synchronized ( wc.strList )
    {
        wc.strList.add( "Added" );
        System.out.println( "Notify for others" );
        wc.strList.notifyAll();
        for ( int i = 0; i < 100; i++ )
        {
            System.out.println( i );
        }
        try
        {
            Thread.sleep( 5000 );
        }
        catch ( InterruptedException e )
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println( "Woke up" );
        System.out.println( "After Notifying" );
    }
    System.out.println( "After synch WaitCheckWaiter" );

}

}

然后是下面的这个

public class WaitCheck implements Runnable{

WaitCheck wc;
List<String> strList = new ArrayList();

public static void main(String[] args) {
    WaitCheck wc = new WaitCheck();
    new Thread(wc).start();
    WaitCheckWaiter wcw = new WaitCheckWaiter(wc);
    new Thread(wcw).start();
}



@Override
public void run() {
    synchronized (strList) {
        if(strList.size() == 0)
        {
            try {
                System.out.println("Just Before wait..");
                strList.wait();
                System.out.println("Just after wait..");
                // printing the added value
                System.out.println("Value : "+strList.get(0));
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        else
        {
            System.out.println("In else statement..!!");
        }
    }
    System.out.println("After synch WaitCheck");

}

}

所以我的理解是,即使我调用notifyAll(),等待线程也无法恢复,直到完成了称为notifyAll()的同步块为止。这是对的还是没有其他确定性行为。

3 个答案:

答案 0 :(得分:3)

Javadoc for the Object.notifyAll method在这个主题上很清楚:

(我加粗的文字)

  

唤醒所有正在此对象的监视器上等待的线程。一种   线程通过调用等待之一在对象的监视器上等待   方法。

     

唤醒的线程将无法继续,直到   当前线程放弃对该对象的锁定。唤醒   线程将以通常的方式与任何其他线程竞争   可能正在积极竞争以同步该对象;对于   例如,唤醒的线程不享有可靠的特权,或者   缺点是成为锁定该对象的下一个线程。

答案 1 :(得分:1)

在大多数操作系统中,线程由一个对象表示,该对象可以根据其状态在不同容器之间移动。这些容器传统上称为“队列”,即使它们不一定实现为实际的先进先出队列。

当线程调用o.wait()时,它的对象从“当前正在运行”队列移动到仅包含等待o.notify()的那些对象的队列。当另一个线程调用o.notify()时,操作系统从该队列中选择一个线程,然后将其移至等待其轮流进入(或返回)synchronized(o)块的线程队列中。

这几乎是o.notify()做的 only 事情。实际上,如果等待o.notify()的线程队列为空,则o.notify()根本不执行任何操作。

o.notifyAll()相同,除了它不移动一个线程,而是移动所有正在等待的线程。

答案 2 :(得分:0)

在有关Thread.sleep(...)的文档中添加到另一个答案:

该线程不会失去任何监视器的所有权。

这意味着至少作为一项基本原则,只要仍然保持任何同步锁,就应该 永远不要 调用Thread.sleep(...)。