如何防止共享同一个对象?

How to prevent sharing same object?

我的程序采用线程数组,它还包含一个由我定义的 "Queue" class,它从 main() 中获取 "Work" 对象并将它们推送到线程 class.

class Queue {
volatile boolean value = false;
int i;
Work[] WI;
public Queue(int num) {
    this.WI = new Work[num];
    this.i = 0;
    }
synchronized void enqueue(Work WI) {
    if (value) {
        try {
            wait();} catch (Exception e) {
            System.out.println(e);
        }
    }
    this.WI[i++] = WI;
    value = true;
    notify();
}
synchronized Work dequeue() {
    if (!value) {
        try {
            wait();} catch (Exception e) {
            System.out.println(e);
        }
    }
    value = false;
    notify();
    return this.WI[i - 1];
 }
}

这是我的线程 class 它需要 "Work" 对象并进行计算。

class Thread_Produce implements Runnable {

Work WI;
Queue q;
int row, column,n,s, start;
Thread t;
public Thread_Produce(Queue q,int n) {
    this.q = q;
    t = new Thread(this);
    this.n = n;
    this.s = 0;
    this.start = 0;
    t.start();
}

public void run() {
        for (int j = 0; j < n; j++) {
                this.WI = (Work) q.dequeue();
                for (int i = 0; i < WI.array1[0].length; i++) {
                    s = s + WI.array1[WI.row][i] * WI.array2[WI.column][i];
                }
                System.out.println(s);
                s = 0;
            }
}

但是尽管我使 "Queue" class 方法同步,但我的线程数组与 "Queue" 共享相同的 "Work" 对象。一个数组在没有正确执行前一个数组的情况下进入 运行 方法。我该怎么办?

不要重新发明轮子,使用现有的:

使用 ConcurrentLinkedQueue 作为您的队列,而不是创建您自己的队列。它是 100% 线程安全的,无需同步。

您的代码如下:

if (condition)
    wait();

不起作用。 wait 方法释放锁并将调用线程置于等待状态。一旦线程从等待中醒来,它必须先获取锁,然后才能让调用等待。但此时线程不知道事情处于什么状态。收到通知并不能保证被通知的线程可以立即获取锁,其他线程可能在通知和获取锁之间采取了行动。

而是始终在循环中调用 wait,这样当您的线程唤醒时,它会在获得锁后检查它正在等待的条件。请参阅 Oracle 教程,尤其是 the Guarded Blocks page.

您还对两个不同的案例使用了通知。当一个线程被通知时,它被任意选择用于通知,它可能与相关的东西有关,也可能不相关,如果通知与碰巧接收到它的线程无关,那么该通知就会丢失。改为使用 notifyall,至少你知道它是否与任何等待线程相关,然后它就会被执行。

不使用标志,而是检查数组中是否有任何内容。