理解多线程技术

5
我有一个关于并发运行的线程和它们对对象锁的问题。据我了解,调用wait()方法的线程会进入等待列表,并允许另一个来自阻塞列表的线程获取对象锁(在同步代码中)。
如果现在拥有对象锁的这个线程调用notify()方法,它将唤醒调用wait()的那个线程,并将其移动到阻塞列表中。
那么调用notify()方法的线程会发生什么?它是否仍然持有对象锁,还是现在加入了等待列表?
问候。
3个回答

5

一个对象只能被一个线程持有锁。在调用wait()notify()方法时,线程必须持有该对象的锁;如果没有持有(例如,因为您没有在该对象上同步),则会出现IllegalMonitorStateException异常。

当您调用wait()方法时,线程会放弃锁并进入等待列表(停止执行)。当wait()方法返回时,线程将再次获得锁。但是,调用notify()方法的线程仍然持有锁,因此在通知线程退出synchronized块或方法以释放对象上的锁之前,等待线程将不会恢复执行。

通过调用notify()方法,线程不会放弃对象上的锁。

可能的事件序列如下:

  • 线程1进入synchronized块,获取对象的锁
  • 线程1在对象上调用wait()方法,放弃锁并停止执行
  • 线程2进入synchronized块,获取对象的锁
  • 线程2在对象上调用notify()方法,但仍然持有锁
  • 线程1被唤醒并尝试获取锁,但无法获取,因为线程2仍然持有锁(因此线程1必须等待锁)
  • 线程2退出synchronized块并释放锁
  • 线程1现在可以获取锁并从wait()方法返回

4
通知线程仍然拥有锁。参见文档第17.14节(页面底部):

只有当当前线程已经锁定了对象的锁时,才应该为该对象调用notify方法。如果对象的等待集不为空,则从等待集中删除某个任意选择的线程并重新启用它以进行线程调度。(当然,该线程在当前线程放弃对象的锁之前无法继续执行。)


1
不会,它会在离开同步块或从同步方法返回时释放锁。除非再次调用wait(),否则它不会回到等待列表中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接