我正在開發具有兩個線程:消費者和生產者的循環緩衝區。 我正在使用主動等待Thread.yield
。 我知道可以用信號量做到這一點,但我想要沒有信號量的緩衝區。具有線程消費者和生產者的循環緩衝區:它獲得一些執行
兩者都有一個共享變量:bufferCircular
。在位置陣列的p
雖然緩衝器未滿的有用的信息,producer
寫入數據,並同時有一些有用的信息consumer
在位置陣列的c
讀取數據。來自BufferCircular
的變量nElem
是尚未讀取的值數據的數量。
該程序運行相當不錯9/10次運行。然後,有時候,它會在屏幕上顯示最後一個元素(循環數爲500)之前在無限循環中得到填充,或者不顯示任何元素。
我認爲可能是一個liveLock,但我找不到這個錯誤。
共享變量:
public class BufferCircular {
volatile int[] array;
volatile int p;
volatile int c;
volatile int nElem;
public BufferCircular(int[] array) {
this.array = array;
this.p = 0;
this.c = 0;
this.nElem = 0;
}
public void writeData (int data) {
this.array[p] = data;
this.p = (p + 1) % array.length;
this.nElem++;
}
public int readData() {
int data = array[c];
this.c = (c + 1) % array.length;
this.nElem--;
return data;
}
}
生產者線程:
public class Producer extends Thread {
BufferCircular buffer;
int bufferTam;
int contData;
public Productor(BufferCircular buff) {
this.buffer = buff;
this.bufferTam = buffer.array.length;
this.contData = 0;
}
public void produceData() {
this.contData++;
this.buffer.writeData(contData);
}
public void run() {
for (int i = 0; i < 500; i++) {
while (this.buffer.nElem == this.bufferTam) {
Thread.yield();
}
this.produceData();
}
}
}
消費者線程:
public class Consumer extends Thread {
BufferCircular buffer;
int cont;
public Consumer(BufferCircular buff) {
this.buffer = buff;
this.cont = 0;
}
public void consumeData() {
int data = buffer.readData();
cont++;
System.out.println("data " + cont + ": " + data);
}
public void run() {
for (int i = 0; i < 500; i++) {
while (this.buffer.nElem == 0) {
Thread.yield();
}
this.consumeData();
}
}
}
主要:
public class Main {
public static void main(String[] args) {
Random ran = new Random();
int tamArray = ran.nextInt(21) + 1;
int[] array = new int[tamArray];
BufferCircular buffer = new BufferCircular(array);
Producer producer = new Producer (buffer);
Consumer consumer = new Consumer (buffer);
producer.start();
consumer.start();
try {
producer.join();
consumer.join();
} catch (InterruptedException e) {
System.err.println("Error with Threads");
e.printStackTrace();
}
}
}
任何幫助將受到歡迎。
甚至沒有讀完整個問題,但'BufferCircular'充滿了嚴重的線程錯誤。易變數組不會使它們的_elements_變爲volatile,並且在volatile中使用'++'也是一個糟糕的想法(tm)。 「易變」不是一種魔法,它是一個窮人的同步,應該非常小心地使用它。 –
我想補充一點,'數組'在這裏不應該是不穩定的,它應該是私人最終的。首先,您需要在這裏創建'writeData()'和'readData()'方法原子或可序列化。最簡單的方法是聲明他們'同步' –
@SergeyTachenov那麼你還推薦使用'AtomicInteger.incrementAndGet()'而不是'++'? – Shondeslitch