等待/通知死锁
我有一个队列,在“添加”和“获取”方法中具有一些阻塞机制,其中第一个线程添加数据,第二个线程获取数据。
public synchronized MyObj getData() {
synchronized (myLock) {
synchronized (this) {
if (isEmpty()) {
wait(0);
}
}
return getData();
}
}
public synchronized void addData(MyObj data) {
if (!isFull()) {
putData(data);
synchronized (this) {
notify();
}
}
}
在上面的代码中,如果第一个线程尝试获取数据并且队列为空,我将通过 wait(0) 进行等待,直到其他线程将数据添加到队列中,然后通过 notification() 释放等待。
现在,当队列已满并且有人尝试向其中添加更多数据时,我想添加另一个“锁”:
public synchronized MyObj getData() {
synchronized (myLock) {
synchronized (this) {
if (isEmpty()) {
wait(0);
}
}
synchronized (this) {
notify();
}
return getData();
}
}
public synchronized void addData(MyObj data) {
synchronized (myLock) {
synchronized (this) {
if (isFull()) {
wait(0);
}
}
}
synchronized (this) {
notify();
}
PutData(data);
}
结果不是我所期望的,我猜我得到了死锁,因为进程被卡住了。
更新
这就是我获取数据的方式:
queueSize--;
startPointer = (startPointer + 1) % mqueueSize;
data = (String) queue[startPointer];
这就是我添加数据的方式
queueSize++;
endPointer = (endPointer + 1) % mqueueSize;
queue[endPointer] = data;
public synchronized boolean isEmpty() {
return queueSize== 0;
}
public synchronized boolean isFull() {
return queueSize== mqueueSize;
}
I have a queue with some blocking mechanism in "Add" and "Get" methods, where first thread adds data and second thread gets data.
public synchronized MyObj getData() {
synchronized (myLock) {
synchronized (this) {
if (isEmpty()) {
wait(0);
}
}
return getData();
}
}
public synchronized void addData(MyObj data) {
if (!isFull()) {
putData(data);
synchronized (this) {
notify();
}
}
}
In the code above, if first thread tries to get data and queue is empty i put in wait via wait(0) until other thread add data to queue an release from waiting via notify().
Now I want to add another "lock" when queue is full and some one tries to add more data to it:
public synchronized MyObj getData() {
synchronized (myLock) {
synchronized (this) {
if (isEmpty()) {
wait(0);
}
}
synchronized (this) {
notify();
}
return getData();
}
}
public synchronized void addData(MyObj data) {
synchronized (myLock) {
synchronized (this) {
if (isFull()) {
wait(0);
}
}
}
synchronized (this) {
notify();
}
PutData(data);
}
The result is not what I expect , I guess that i get a dead lock cause process is stuck.
UPDATE
This is how I get data:
queueSize--;
startPointer = (startPointer + 1) % mqueueSize;
data = (String) queue[startPointer];
this is how i add data
queueSize++;
endPointer = (endPointer + 1) % mqueueSize;
queue[endPointer] = data;
public synchronized boolean isEmpty() {
return queueSize== 0;
}
public synchronized boolean isFull() {
return queueSize== mqueueSize;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
为什么有三个
synchronized
语句?wait(0)
仅释放this
上的锁,因此只需保留该锁并从方法和中转储
synchronized
同步(myLock)。每当您对某个对象调用 wait(在本例中您正在调用
this
)时,该对象上的锁就会自动释放,以允许其他线程继续进行。但是您永远不会在myLock
上调用 wait (也不应该,因为您已经在调用this
了)。该部分是多余的并导致死锁。考虑这种情况:应该添加的线程获取了
myLock
上的锁,但发现队列已满,因此它等待。此等待不会释放myLock
上的锁定。另一个线程想要获取数据,但无法进入synchronized
块,因为第一个线程没有释放myLock
上的锁。结论:删除
synchronized(myLock)
块。Why do you have three
synchronized
statements? Thewait(0)
only releases the lock onthis
, so just keep that one and dump thesynchronized
from the method and thesynchronized(myLock)
.Whenever you call wait on some object (in this case you are calling on
this
), the lock on that object is automatically released to allow the other thread to proceed. But you are never calling wait onmyLock
(and nor should you, because you are calling onthis
already). That part is redundant and causes the deadlock.Consider this scenario: the thread that is supposed to add takes the lock on
myLock
but finds the queue full, so it waits. This wait does not release the lock onmyLock
. The other thread wants to take data but cannot enter thesynchronized
block because the first thread did not release the lock onmyLock
.Conclusion: remove the
synchronized(myLock)
blocks.为什么你不看看java.lang. util.BlockingQueue。也许它对您的情况有用。
特别是看看 java.util.LinkedBlockingQueue,如果您在构造函数中指定队列的容量,则队列将阻塞。
Why you don't take a look in java.util.BlockingQueue. Probably it will be useful in your situation.
Particularly take a look at java.util.LinkedBlockingQueue, where if you specify the queue's capacity in the constructor, then the queue will block.
从方法签名中删除
synchronized
关键字,因为这意味着您持有整个方法调用的this
监视器 -synchronized(this)
块只是多余的。编辑:
...然后在
myLock
而不是this
上调用 wait 和通知。并且完全忘记在this
上进行同步。这是因为在等待时(在当前代码中的this
上),您没有释放myLock
锁,因此其他线程无法访问通知()。
Remove the
synchronized
keyword from your method signatures, as that implies you hold thethis
monitor for the whole method call -- thesynchronized(this)
blocks are simply redundant.EDIT:
...Then call wait and notify on
myLock
rather thanthis
. And forget completely about synchronizing onthis
. This is because while waiting (onthis
in your current code), you're not releasing themyLock
lock, so the other thread is not able to get tonotify()
.将
if
替换为while
。如果集合确实变得不空/不满,那么仔细检查不会有什么坏处。你真的不需要两把锁。单锁几乎也可以工作,而且应该简单得多。
当事情发生变化时,所有线程都会被唤醒。但如果他们无法完成工作,他们将
等待
下一个通知
。Replace
if
withwhile
. It won't hurt to double check, if the collection really become not empty/not full.You don't really need two locks. Single lock will work almost as well and should be much simpler.
All threads will wake up when something changes. But if they can't do their work, they will
wait
for nextnotify
.正如已经提到的,您的代码有太多
synchronized
注释。此外,wait
的条件是在if
条件中检查的,但理想情况下应该在while
循环中检查,以避免 虚假唤醒。以下是修复这些问题的代码概要。As already mentioned, your code has too many
synchronized
annotations. Also, the condition towait
on is checked in anif
conditional, but it should ideally be checked in awhile
loop to avoid spurious wakeups. Here is the outline of the code that fixes these.