唤醒 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. 线程 #1 首先调用 synchronized (flag) 并进入保护区。
  2. 线程 #2 和 #3 调用 synchronized (flag) 但它们被锁定,直到线程 #1 解锁。
  3. 线程 #1 的 pointer 值等于缓冲区长度,因此它调用 sampledSelection();,将 pointer 重置为 0,调用 notifyAll(),然后解锁。
  4. 线程 #2(比方说)现在进入 synchronized 部分。它的 pointer 值不相等,所以它转到 wait() 解锁。
  5. 线程 #3 现在进入 synchronized 部分。它的 pointer 值不相等,所以它转到 wait() 解锁。

如果没有人回来打电话notifyAll()那么他们将永远等待。

如您所知,重要的是要认识到 notifyAll() 方法只有在线程 已经在等待 时才起作用。通常应该发生的是线程应该查看条件字段以查看它们是否应该等待。

另一件需要注意的事情是确保你 synchronized 所在的对象是一个常量。在你的情况下 flag 应该被定义为:

private final Object flag = new Object();

如果您的 flag 可以分配给另一个值,那么线程将不会锁定(或发出信号)在同一对象上,这会导致问题。始终确保锁定 final 对象。

希望这对您有所帮助。