我针对生产者消费者问题编写了多线程代码,其中我在消费者和生产者线程的运行方法中编写了同步块,该块锁定了共享列表(我假设) 因此,问题在于,列表上是否会有锁定,因为每个线程都有自己的同步块,但是它们共享同一个列表实例
public class Main {
static boolean finishFlag=false;
final int queueSize = 20;
List<Integer> queue = new LinkedList<>();
Semaphore semaphoreForList = new Semaphore(queueSize);
public Main(int producerCount,int consumerCount) {
while(producerCount!=0) {
new MyProducer(queue,semaphoreForList,queueSize).start(); //produces the producer
producerCount--;
}
while(consumerCount!=0) {
new MyConsumer(queue,semaphoreForList,queueSize).start(); //produces the consumer
consumerCount--;
}
}
public static void main(String args[]) {
/*
* input is from command line 1st i/p is number of producer and 2nd i/p is number of consumer
*/
try {
Main newMain = new Main(Integer.parseInt(args[0]),Integer.parseInt(args[1]));
try {
Thread.sleep(30000);
}
catch(InterruptedException e) {
}
System.out.println("exit");
finishFlag=true;
}
catch(NumberFormatException e) {
System.out.println(e.getMessage());
}
}
}
class MyProducer extends Thread{
private List<Integer> queue;
Semaphore semaphoreForList;
int queueSize;
public MyProducer(List<Integer> queue, Semaphore semaphoreForList,int queueSize) {
this.queue = queue;
this.semaphoreForList = semaphoreForList;
this.queueSize = queueSize;
}
public void run() {
while(!Main.finishFlag) {
try {
Thread.sleep((int)(Math.random()*1000));
}
catch(InterruptedException e) {
}
try {
if(semaphoreForList.availablePermits()==0) {//check if any space is left on queue to put the int
System.out.println("no more spaces left");
}
else {
synchronized(queue) {
semaphoreForList.acquire(); //acquire resource by putting int on the queue
int rand=(int)(Math.random()*10+1);
queue.add(rand);
System.out.println(rand+" was put on queue and now length is "+(queueSize-semaphoreForList.availablePermits()));
}
}
}
catch(InterruptedException m) {
System.out.println(m);
}
}
}
}
public class MyConsumer extends Thread{
private List<Integer> queue; //shared queue by consumer and producer
Semaphore semaphoreForList;
int queueSize;
public MyConsumer(List<Integer> queue, Semaphore semaphoreForList,int queueSize) {
this.queue = queue;
this.semaphoreForList = semaphoreForList;
this.queueSize = queueSize;
}
public void run() {
while(!Main.finishFlag) {//runs until finish flag is set to false by main
try {
Thread.sleep((int)(Math.random()*1000));//sleeps for random amount of time
}
catch(InterruptedException e) {
}
if((20-semaphoreForList.availablePermits())==0) {//checking if any int can be pulled from queue
System.out.println("no int on queue");
}
else {
synchronized(queue) {
int input=queue.remove(0);//releases the resource(position in queue) by pulling the int out of the queue and computing factorial
semaphoreForList.release();
int copyOfInput=input;
int fact=1;
while(copyOfInput!=0) {
fact = fact*copyOfInput;
copyOfInput--;
}
System.out.println(input+" was pulled out from queue and the computed factorial is "+fact+
" the remaining length of queue is "+(queueSize-semaphoreForList.availablePermits()));
}
}
}
}
}
答案 0 :(得分:0)
我宁愿建议使用java.lang.Object
方法wait()
和notify()
来创建消费者生产者算法。使用这种方法,队列不会被无休止的重复和不必要的synchronized
语句阻塞,我认为这是一种性能更高且“事件驱动”的解决方案。
此链接可能会有所帮助- https://www.geeksforgeeks.org/producer-consumer-solution-using-threads-java/
答案 1 :(得分:0)
是的,互斥体/监视器与Java Object
实例相关联,该实例是此实例中的共享列表。这意味着所有线程都锁定相同的互斥锁(与queue
关联,并通过该互斥锁进行同步。
因此,好的一面是:您的程序实际上是线程安全的。
但是,实际上,附加信号量在各种方面并没有多大意义:
正如AnDus所提到的,这可以通过使用充当条件变量的wait和notify方法来更好地解决。您很可能甚至需要两个,一个用于解除生产者的封锁,另一个用于解除消费者的封锁。
通常,如果这不是编码工作,请使用已经实现所需功能的类。在这种情况下,java.util.concurrent.BlockingQueue
似乎就是您想要的。