我在这里要做的是按偶数消费者打印偶数,按奇数消费者打印奇数。evenodd
方法基本上消耗了任何数字并打印(无论是偶数还是奇数)。我有2个even
使用者线程,2个odd
使用者线程,2个evenodd
使用者线程和3个producer
线程。
我对信号量概念不熟悉,因此尝试使用它。当我删除evenodd
方法和相关线程时,我得到正确的输出,即偶数由偶数线程组成,奇数由奇数线程组成。但是,当我再次放置evenodd
方法和evenodd
线程时,出现死锁。
如果有人可以在这方面指导我,我哪里出了问题以及如何解决它,这将非常有帮助。请说明我如何实现evenodd
方法,以便它可以正常工作。
package lab61;
import java.util.LinkedList;
import java.util.Random;
import java.util.concurrent.Semaphore;
public class Process {
Semaphore empty;
Semaphore full;
Semaphore even;
Semaphore odd;
Semaphore mutex;
//Semaphore evenodd;
boolean evenb;
boolean oddb,eo;
LinkedList<Integer> list;
Random random;
public Process(int capacity){
list=new LinkedList<Integer>();
empty=new Semaphore(capacity);
full=new Semaphore(0,true);
mutex=new Semaphore(1,true);
even=new Semaphore(0,true);
evenb=false;
oddb=false;
eo=false;
odd=new Semaphore(0,true);
//evenodd = new Semaphore(0,true);
random=new Random();
}
public void Producer() throws InterruptedException{
while(true){
int a=random.nextInt(100);
empty.acquire();
mutex.acquire();
list.add(a);
System.out.println("Producing "+a);
System.out.println(list);
if((list.get(0)%2)==0){
if(!evenb){
even.release();
evenb = true;
}
}else if((list.get(0)%2)==1){
if(!oddb){
odd.release();
oddb = true;
}
}
/*if(((list.get(0)%2)==0)||((list.get(0)%2)==1)){
if(!eo){
evenodd.release();
eo = true;
}
}*/
mutex.release();
full.release();
}
}
public void consumereven() throws InterruptedException{
while(true){
//Thread.sleep(2000);
even.acquire();
Thread.sleep(2000);
full.acquire();
mutex.acquire();
int value = list.removeFirst();
System.out.println("I am the even consumer "+ value);
evenb = false;
System.out.println(list);
mutex.release();
empty.release();
}
}
public void consumerodd() throws InterruptedException{
while(true){
//Thread.sleep(2000);
odd.acquire();
Thread.sleep(2000);
full.acquire();
//odd.acquire();
mutex.acquire();
int value = list.removeFirst();
System.out.println("I am the odd consumer "+ value);
System.out.println(list);
oddb = false;
mutex.release();
empty.release();
}
}
public void evenodd() throws InterruptedException {
while(true){
full.acquire();
mutex.acquire();
int value = list.removeFirst();
System.out.println("i am the evenodd consumer " + value );
if((list.get(0)%2)==0){
if(oddb=true){
odd.acquire();
oddb=false;
}
if(evenb==false){
even.release();
evenb = true;
}
}
else if((list.get(0)%2)==1){
if(evenb=true){
even.acquire();
evenb=false;
}
if(oddb==false){
odd.release();
oddb = true;
}
}
System.out.println(list);
mutex.release();
empty.release();
}
}
}
package lab61;
import lab6.producer;
public class App {
public static void main(String[] args) throws InterruptedException{
Process p=new Process(10);
Thread producer1=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
p.Producer();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread producer2=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
p.Producer();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread producer3=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
p.Producer();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread consumereven1=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
p.consumereven();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread consumereven2=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
p.consumereven();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread consumerodd1=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
p.consumerodd();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread consumerodd2=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
p.consumerodd();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread evenodd1=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
p.evenodd();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread evenodd2=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
p.evenodd();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
producer1.start();
producer2.start();
producer3.start();
consumereven1.start();
consumereven2.start();
consumerodd1.start();
consumerodd2.start();
evenodd1.start();
evenodd2.start();
producer1.join();
producer2.join();
producer3.join();
consumereven1.join();
consumereven2.join();
consumerodd1.join();
consumerodd2.join();
evenodd1.join();
evenodd2.join();
}
}
最佳答案
该代码可能导致死锁,因为consumereven()
和consumerodd()
方法在even
和odd
信号量之前获取full
或mutex
信号量,而evenodd()
方法获取full
和在mutex
或even
信号灯之前的信号灯。这导致这样的情况,例如,运行odd
的线程具有consumereven()
信号量,但是在等待even
信号量时被阻塞,而运行evenodd()的线程具有full
信号量,但是被阻塞在full
信号量上,因此两个线程处于死锁状态。
为防止死锁,当您使用多个锁时,最好始终以相同的顺序获取它们,无论它们在何处使用,并以相反的获取顺序释放它们。