2016-04-26 66 views
4

Java线程中Java线程的状态可以通过举行:什么是等待,无法获得锁

  1. 无法获取的锁。
  2. 正在通过wait()方法举行。

以上两种情况在Java线程状态方面有什么区别?

考虑以下简单的代码:

synchronized(object) { 
     object.wait(); 
     System.out.println("Completed."); 
    } 

如果两个线程(说的ThreadA和ThreadB)都被关押在wait()方法。例如,当另一个线程调用notifyAll()时,ThreadA将从等待中恢复并获取对象的锁定并继续。 ThreadB也会复活,但无法获取对象的锁定并保持到ThreadA退出同步块为止。 ThreadB然后获得锁并继续。

其结果将是两个“已完成”被打印。

在这个例子中,必须有当从ThreadB变化“正在举行的wait()”到“正在举行,因为它是无法获得对象的锁”的时间。

我想知道它是如何工作的内部Java编写的。请帮忙。

+2

基于'enum Thread.State'的Javadoc(我还没有试过实验),状态应该从'WAITING'变成'BLOCKED'。也许你可以做实验,看看我是否正确。 –

+1

这个[answer](http://stackoverflow.com/a/28726421/6238076)已经非常详细地解释了所有等待线程在收到通知后的行为。 – gdlmx

回答

2

的区别是在object.wait()状态释放object所有的显示器所持有的该线程,它会在系统中重新获取所有的线程竞争再次监视。这使得wait()成为特殊状态。

所以你的情况时AB(线程A和线程B)处于观望状态,他们没有监视器同步object,他们都已经从执行暂停,直到其他线程调用object.notify()object.notifyAll()。当notifyAll()被称为JVM唤醒所有线程(在这种情况下AB)在object.wait()状态和他们竞争,以获得当前​​块的监视器。如果调用notify(),则JVM随机选取A或B.

这是这里要注意的是,JVM没有通知任何特定的线程,这就是为什么每一个等待的线程在一个while(notify_condition_for_me)循环等待,即验证如果等待病情已如果没有它在object.wait()状态去再次。

所以正确的代码应该是

synchronized(object) { 
    while(myResourceArrived) {//like URL data, JDBC data or something 
     object.wait(); 
    } 
    System.out.println("Completed."); 
} 

ABobject.wait()状态,他们已经释放了所有他们之前持有object这是等待​​块之外的显示器,所以任何其他线程将通过获取object的已发布显示器立即能够进入该区块。

2

看看Thread.State,更具体地说WAITINGBLOCKED状态。

如果您对内部实现感兴趣,都可以使用LockSupport.park()LockSupport.unpark(Thread)来实现,而实际上它们是如何在大多数地方实现的。

P.S.如果你有兴趣,这里是在OpenJDK park()实现了Windows (line 4946)Linux (line 5808),这里是wait()/notify()/notifyAll()执行(1457线)。他们有很好的评论,如果一看起来太复杂,就给它一些时间。在object.wait()状态,并等待object监视器上的锁福利之间