Java 我的代码是否处于死锁状态?
在编译下面的代码时,它似乎处于死锁状态,我不知道如何修复它。我试图将管道作为一系列线程作为缓冲区连接在一起,每个线程都可以读取管道中的前一个节点,并最终写入下一个节点。总体目标是将随机生成的数据数组列表分散到10个线程上,并对其进行排序Java 我的代码是否处于死锁状态?,java,multithreading,thread-safety,Java,Multithreading,Thread Safety,在编译下面的代码时,它似乎处于死锁状态,我不知道如何修复它。我试图将管道作为一系列线程作为缓冲区连接在一起,每个线程都可以读取管道中的前一个节点,并最终写入下一个节点。总体目标是将随机生成的数据数组列表分散到10个线程上,并对其进行排序 class Buffer{ // x is the current node private int x; private boolean item; private Lock lock = new ReentrantLo
class Buffer{
// x is the current node
private int x;
private boolean item;
private Lock lock = new ReentrantLock();
private Condition full = lock.newCondition();
private Condition empty = lock.newCondition();
public Buffer(){item = false;}
public int read(){
lock.lock();
try{
while(!item)
try{full.await();}
catch(InterruptedException e){}
item = false;
empty.signal();
return x;
}finally{lock.unlock();}
}
public void write(int k){
lock.lock();
try{
while(item)
try{empty.await();}
catch(InterruptedException e){}
x = k; item = true;
full.signal();
}finally{lock.unlock();}
}
}
class Pipeline extends Thread {
private Buffer b;
//private Sorted s;
private ArrayList<Integer> pipe; // array pipeline
private int ub; // upper bounds
private int lb; // lower bounds
public Pipeline(Buffer bf, ArrayList<Integer> p, int u, int l) {
pipe = p;ub = u;lb = l;b = bf;//s = ss;
}
public void run() {
while(lb < ub) {
if(b.read() > pipe.get(lb+1)) {
b.write(pipe.get(lb+1));
}
lb++;
}
if(lb == ub) {
// store sorted array segment
Collections.sort(pipe);
new Sorted(pipe, this.lb, this.ub);
}
}
}
class Sorted {
private volatile ArrayList<Integer> shared;
private int ub;
private int lb;
public Sorted(ArrayList<Integer> s, int u, int l) {
ub = u;lb = l;shared = s;
// merge data to array from given bounds
}
}
class Test1 {
public static void main(String[] args) {
int N = 1000000;
ArrayList<Integer> list = new ArrayList<Integer>();
for(int i=0;i<N;i++) {
int k = (int)(Math.random()*N);
list.add(k);
}
// write to buffer
Buffer b = new Buffer();
b.write(list.get(0));
//Sorted s = new Sorted();
int maxBuffer = 10;
int index[] = new int[maxBuffer+1];
Thread workers[] = new Pipeline[maxBuffer];
// Distribute data evenly over threads
for(int i=0;i<maxBuffer;i++)
index[i] = (i*N) / maxBuffer;
for(int i=0;i<maxBuffer;i++) {
// create instacen of pipeline
workers[i] = new Pipeline(b,list,index[i],index[i+1]);
workers[i].start();
}
// join threads
try {
for(int i=0;i<maxBuffer;i++) {
workers[i].join();
}
} catch(InterruptedException e) {}
boolean sorted = true;
System.out.println();
for(int i=0;i<list.size()-1;i++) {
if(list.get(i) > list.get(i+1)) {
sorted = false;
}
}
System.out.println(sorted);
}
}
启动run方法时,所有线程都将阻塞,直到第一个线程达到full.await。然后一个接一个地,所有线程都将到达full.wait。他们将等待这个信号 然而,full.signal发生的唯一地方是在其中一个读取方法完成之后。 由于该信号从未触发,因此无法到达该代码,因此所有线程都在等待 简而言之,只有在1次读取完成后,写入才会触发。 如果你颠倒逻辑,开始清空,用信号等写缓冲区,然后线程尝试读取,我希望它会工作 一般来说,您希望在读取管道之前先将其写入管道。或者没有什么可读的 我希望我没有误读您的代码,但这是我在第一次扫描时看到的。您的缓冲区类在读写模式之间切换。每次读取之后都必须有一次写入,然后是读取,依此类推 最初在main方法中写入缓冲区 现在,您的一个线程在Pipelinerun中到达ifb.read>pipe.getlb+1{。如果该条件的计算结果为false,则不会写入任何内容。而且由于每个其他线程都必须是相同的ifb.read,因此您最终会遇到无法进行的所有读取线程。您必须在else分支中写入或允许多次读取