唤醒 java 中的等待线程
Wake waiting threads in java
我有 4 个线程同时填充一个 50000000x4 矩阵。为了确保写入的安全性,我使用了 AtomicInteger 作为指针。每次迭代每个线程都将指针值复制到 threadPointer 中并用它来填充一个 .
第一个获得指针 == 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()
没有唤醒等待 threads.How 我可以解决这个问题吗?
听起来您已经明白了,但为了后代...
My problem is that notifyAll doesn't wake the waiting threads. How can I fix this?
是的,你这里有一个经典的比赛条件。假设有 3 个线程大约同时出现并执行 pointer.getAndAdd(1)
。
- 线程 #1 首先调用
synchronized (flag)
并进入保护区。
- 线程 #2 和 #3 调用
synchronized (flag)
但它们被锁定,直到线程 #1 解锁。
- 线程 #1 的
pointer
值等于缓冲区长度,因此它调用 sampledSelection();
,将 pointer
重置为 0,调用 notifyAll()
,然后解锁。
- 线程 #2(比方说)现在进入
synchronized
部分。它的 pointer
值不相等,所以它转到 wait()
解锁。
- 线程 #3 现在进入
synchronized
部分。它的 pointer
值不相等,所以它转到 wait()
解锁。
如果没有人回来打电话notifyAll()
那么他们将永远等待。
如您所知,重要的是要认识到 notifyAll()
方法只有在线程 已经在等待 时才起作用。通常应该发生的是线程应该查看条件字段以查看它们是否应该等待。
另一件需要注意的事情是确保你 synchronized
所在的对象是一个常量。在你的情况下 flag
应该被定义为:
private final Object flag = new Object();
如果您的 flag
可以分配给另一个值,那么线程将不会锁定(或发出信号)在同一对象上,这会导致问题。始终确保锁定 final
对象。
希望这对您有所帮助。
我有 4 个线程同时填充一个 50000000x4 矩阵。为了确保写入的安全性,我使用了 AtomicInteger 作为指针。每次迭代每个线程都将指针值复制到 threadPointer 中并用它来填充一个 . 第一个获得指针 == 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()
没有唤醒等待 threads.How 我可以解决这个问题吗?
听起来您已经明白了,但为了后代...
My problem is that notifyAll doesn't wake the waiting threads. How can I fix this?
是的,你这里有一个经典的比赛条件。假设有 3 个线程大约同时出现并执行 pointer.getAndAdd(1)
。
- 线程 #1 首先调用
synchronized (flag)
并进入保护区。 - 线程 #2 和 #3 调用
synchronized (flag)
但它们被锁定,直到线程 #1 解锁。 - 线程 #1 的
pointer
值等于缓冲区长度,因此它调用sampledSelection();
,将pointer
重置为 0,调用notifyAll()
,然后解锁。 - 线程 #2(比方说)现在进入
synchronized
部分。它的pointer
值不相等,所以它转到wait()
解锁。 - 线程 #3 现在进入
synchronized
部分。它的pointer
值不相等,所以它转到wait()
解锁。
如果没有人回来打电话notifyAll()
那么他们将永远等待。
如您所知,重要的是要认识到 notifyAll()
方法只有在线程 已经在等待 时才起作用。通常应该发生的是线程应该查看条件字段以查看它们是否应该等待。
另一件需要注意的事情是确保你 synchronized
所在的对象是一个常量。在你的情况下 flag
应该被定义为:
private final Object flag = new Object();
如果您的 flag
可以分配给另一个值,那么线程将不会锁定(或发出信号)在同一对象上,这会导致问题。始终确保锁定 final
对象。
希望这对您有所帮助。