提问人:Suvam Roy 提问时间:2/1/2023 最后编辑:Mark RotteveelSuvam Roy 更新时间:2/1/2023 访问量:66
无法理解此多线程异常行为
Can't understand this multi-threading exception behavior
问:
根据 ReentrantLock.newCondition() 的文档,调用线程在调用信令方法之前需要拥有一个锁:
如果在调用任何 Condition 等待或信号方法时未保持此锁,则会引发 IllegalMonitorStateException。
事实上,这是我尝试时看到的:
java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.signalAll(AbstractQueuedSynchronizer.java:1954)
at PingPongPrinter_.printPing(PingPong2.java:35)
at WorkerPing.run(PingPong2.java:53)
at java.lang.Thread.run(Thread.java:748)
那么为什么这个限制存在于 ?我相信C++中没有这样的限制。java.util.concurrent.locks.ReentrantLock
答:
1赞
rgnt
2/1/2023
#1
对原始问题的回答
在发出信号之前,您正在解锁与条件关联的锁。从文档:
在调用此方法时,实现可能(并且通常确实)要求当前线程保留与此 Condition 关联的锁。实现必须记录此前提条件以及未保持锁定时采取的任何操作。通常,将引发异常,例如 IllegalMonitorStateException。
此外,仅锁定修改要调节的值所需的时间。
void printPong() throws Exception {
// wait for pong condition
while (isPing) {
blockPong.await();
}
rlock.lock();
isPing = true; // modify value
blockPing.signalAll(); // signal ping
rlock.unlock();
System.out.println("Pong");
}
void printPing() throws Exception {
// wait for ping condition
while (!isPing) {
blockPing.await();
}
rlock.lock();
isPing = false; // modify value
blockPong.signalAll(); // signal pong
rlock.unlock();
System.out.println("Ping");
}
对修改问题的回答
那么,为什么java.util.concurrent.locks.ReentrantLock中存在此限制呢?我相信C++中没有这样的限制。
因为是相互排斥的。它提供在任何给定时间对单个线程的访问。这是一个设计选择。ReentrantLock
在 C++ 中,还要求您拥有资源的互斥锁才能发出信号。std::condition_variable
评论
0赞
Suvam Roy
2/1/2023
您能简化一下文档吗?我不太明白
评论
object.wait()
object.notify()
synchronized(object)