我有4个线程同时填充50000000x4矩阵。为了确保写入的安全性,我使用了AtomicInteger作为指针。每次迭代每个线程将指针值复制到threadPointer并用它来填充a。 获取指针== buffer.length的第一个线程启动一个例程,将缓冲区刷新到内存中。此时的其他线程应该等待线程完成其工作。 这是我的代码:
if ((threadPointer = pointer.getAndAdd(1)) >= buffer.length ){
synchronized (flag){
if(threadPointer == buffer.length){
sampledSelection();
pointer.set(0);
threadPointer = pointer.getAndAdd(1);
flag.notifyAll();
}else{
System.out.println("waiting");
flag.wait();
threadPointer = pointer.getAndAdd(1);
System.out.println("Awaken!");
}
}
}
我的问题是notifyAll()
没有唤醒等待的线程。我该如何解决这个问题?
答案 0 :(得分:1)
这听起来像你想出来的但后代......
我的问题是notifyAll不会唤醒等待的线程。我该如何解决这个问题?
是的,你在这里有一个经典的竞争条件。我们假设有3个主题在同一时间内执行pointer.getAndAdd(1)
。
synchronized (flag)
并进入受保护区域。 synchronized (flag)
但它们被锁定,直到第1号线解锁。pointer
的值等于缓冲区长度,因此调用sampledSelection();
,将pointer
重置为0,调用notifyAll()
,然后解锁。synchronized
部分。它的pointer
值不相等,因此可以解锁wait()
。synchronized
部分。它的pointer
值不相等,因此可以解锁wait()
。如果没有人回来致电notifyAll()
,那么他们将永远等待。
正如您已经想到的那样,重要的是要意识到notifyAll()
方法唯一有效的方法是线程已经在等待。通常情况下,线程应该查看条件字段以查看它们是否应该等待。
需要注意的另一件事是确保您synchronized
上的对象是常量。在您的情况下,flag
应定义为:
private final Object flag = new Object();
如果您的flag
可以分配给另一个值,那么线程将不会锁定(或发出信号)在同一个对象上,这会导致问题。始终确保锁定final
对象。
希望这有帮助。