使用同步的生产者-消费者
我编写了代码来实现生产者-消费者问题,它似乎工作正常,不需要同步。这可能吗?
如何测试代码并检查它是否确实正常工作?我如何知道是否会发生死锁?现在,我没有跳出循环(即生产者不断插入,消费者不断在无限循环中消费)。我使用大小为 3 的循环队列(为了简单起见)作为共享资源。
这是我的代码:
import java.util.*;
public class PCImpl implements Runnable
{
Thread t;
QforPC qObj;
public static void main(String[] args)
{
QforPC qObject=new QforPC();
//These create 2 different objects! Each object has it's own thread of execution.
//Synchronization is needed when 2 threads use the same object
new PCImpl("Producer",qObject);
new PCImpl("Consumer",qObject);
}
PCImpl(String name,QforPC qObj)
{
this.qObj=qObj;
t=new Thread(this,name);
t.start();
}
public void run()
{
if(Thread.currentThread().getName().equals("Producer"))
{
while(true)
{
Random rgen=new Random();
int n=rgen.nextInt(100);
if(n!=0)
qObj.Producer(n);
try
{
Thread.sleep(200);
}
catch(InterruptedException e)
{
}
}
}
if(Thread.currentThread().getName().equals("Consumer"))
{
while(true)
{
try
{
Thread.sleep(1500);
}
catch(InterruptedException e)
{
}
qObj.Consumer();
}
}
}
}
public class QforPC
{
int[] q={0,0,0};
int r=0,f=0;
public void Producer(int item)
{
if(r!=q.length && canProducer())
{
q[r]=item;
System.out.println("The item inserted into the queue is:"+ item);
r++;
}
if(r==q.length && f>0)
r=0;
else if(r==q.length && f==q.length)
{
r=0;
f=0;
}
}
public void Consumer()
{
int item;
System.out.println("The value of isQueue empty is:"+ isEmpty());
if(f!=q.length && isEmpty()==false)
{
System.out.println("Entered the consumer method");
item=q[f];
System.out.println("The item fetched from the queue is:"+item);
q[f]=0;
f++;
}
if(f==q.length && r<f)
f=0;
}
public boolean isEmpty()
{
for(int k=0;k<q.length;k++)
{
if(q[k]==0 && k==q.length-1)
return true;
}
return false;
}
public boolean canProducer()
{
for(int k=0;k<q.length;k++)
{
if(q[k]==0)
return true;
}
return false;
}
}
I wrote code to implement the Producer-Consumer problem and it seems to be working fine without the need to synchronize.Is it possible?
How do I test the code and check if it is actually working right or not? How do I know if deadlock will occur? Right now,I am not breaking out of the loops(i.e. the Producer keeps inserting and the consumer keeps consuming in an infinite loop).I am using a circular queue of size 3(for sake of simplicity) as the shared resource.
Here is my code:
import java.util.*;
public class PCImpl implements Runnable
{
Thread t;
QforPC qObj;
public static void main(String[] args)
{
QforPC qObject=new QforPC();
//These create 2 different objects! Each object has it's own thread of execution.
//Synchronization is needed when 2 threads use the same object
new PCImpl("Producer",qObject);
new PCImpl("Consumer",qObject);
}
PCImpl(String name,QforPC qObj)
{
this.qObj=qObj;
t=new Thread(this,name);
t.start();
}
public void run()
{
if(Thread.currentThread().getName().equals("Producer"))
{
while(true)
{
Random rgen=new Random();
int n=rgen.nextInt(100);
if(n!=0)
qObj.Producer(n);
try
{
Thread.sleep(200);
}
catch(InterruptedException e)
{
}
}
}
if(Thread.currentThread().getName().equals("Consumer"))
{
while(true)
{
try
{
Thread.sleep(1500);
}
catch(InterruptedException e)
{
}
qObj.Consumer();
}
}
}
}
public class QforPC
{
int[] q={0,0,0};
int r=0,f=0;
public void Producer(int item)
{
if(r!=q.length && canProducer())
{
q[r]=item;
System.out.println("The item inserted into the queue is:"+ item);
r++;
}
if(r==q.length && f>0)
r=0;
else if(r==q.length && f==q.length)
{
r=0;
f=0;
}
}
public void Consumer()
{
int item;
System.out.println("The value of isQueue empty is:"+ isEmpty());
if(f!=q.length && isEmpty()==false)
{
System.out.println("Entered the consumer method");
item=q[f];
System.out.println("The item fetched from the queue is:"+item);
q[f]=0;
f++;
}
if(f==q.length && r<f)
f=0;
}
public boolean isEmpty()
{
for(int k=0;k<q.length;k++)
{
if(q[k]==0 && k==q.length-1)
return true;
}
return false;
}
public boolean canProducer()
{
for(int k=0;k<q.length;k++)
{
if(q[k]==0)
return true;
}
return false;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您尝试做的是使用忙等待来实现同步。在伪代码中,您基本上要做的是:
您的代码将正常工作,直到生产者和消费者同时尝试执行 Produce() 和 Consumer() 。换句话说,其中任何一种可能不会经常发生,但绝对有可能并且一定会发生!
在Java中,ConcurrentLinkedQueue实现了共享缓冲区的无等待算法。如果你环顾四周,我确信还有其他实现。
What you have tried to do is implement synchronization using busy-waiting. In pseudo code what you are basically doing is:
You code will work fine, till the the Producer and Consumer simultaneously try to execute produce() and consume(). In other words, either one of the This might not be very often, but is definitely possible and will definitely happen!
In Java, ConcurrentLinkedQueue to implements a wait-free algorithm for a shared buffer. I'm sure that are other implementations if you look around.
不存在
生产者-消费者问题
这样的事情。生产者-消费者是一种设计模式,它可能是也可能不是问题解决方案的有效实现,而不是问题本身。我确信有很多生产者-消费者实现不需要同步。这完全取决于您想要完成的任务以及您正在生成/消耗的数据类型。
另外,如果你想说你的实现在没有同步的情况下也能工作,那么你必须有一个问题需要解决。工作是做什么的?我不知道你在做什么。
There's no such thing as
the Producer-Consumer problem
. Producer-Consumer is a design pattern that may or may not be an effective implementation of a solution to a problem, not a problem in and of itself.I'm SURE there are plenty of producer-consumer implementations that don't require synching. It entirely depends on what you're trying to accomplish and what kind of data you're producing/consuming.
Also, you have to have a problem to solve if you want to say you're implementation works without synchronizing. Works at doing what? I have no idea what you're doing.
可以使用无锁队列来完成,但不是这样,我建议您阅读《Java Concurrency in Practice》。如果您的代码同时被多个线程访问,您将遇到许多错误,您将遇到发布和同步问题!但正如 Farlmarri 所说,这取决于此代码的使用。
It can be done with a lock free queue, but not like this, i recommend that you read Java Concurrency in Practice. If your code is access by multiple threads at the same time you will have many erros on that, you have publication and syncronizations problems!! But like Farlmarri said it depends on the usage of this code.
实际上,您并没有解决生产者/消费者问题,而只是绕过它:)
您的代码之所以有效,是因为时间安排,并且因为如果两个线程之一无法放置/检索它所请求的资源,它基本上会休眠一段时间并重试。尽管这个工作(当您不必立即处理事件时)它会浪费 CPU 时间。
这就是为什么强烈建议使用信号量来解决此类问题,您可以在此处阅读
http://en .wikipedia.org/wiki/Producer-consumer_problem
再见
you are actually not solving the producer/consumer problem but just walking around it :)
Your code works because of the timing and because of the fact if one of the two threads fails putting/retrieving the resource it asks for it basically sleeps for a while and tries again. Although this worsk (when you do not have to immediatly handle an event) it wastes CPU time.
That is why semaphores are strongly suggested to address this kind of issue as you can read here
http://en.wikipedia.org/wiki/Producer-consumer_problem
bye