【跪求】用C#写的生产者-消费者 出了问题
- C# code
using System;using System.Collections.Generic;using System.Text;using System.Threading;namespace ThreadTestProject{ //LetSynchronized用来存放和取出缓冲区变量 public class LetSynchronized { //定义了只有三个字节的缓冲区 private int[] buffer =new int[1]; //确认缓冲区内已放数值的个数 private int bufferCount = 0; //确定读写的位置 private int readLocation = 0, writeLocation = 0; public LetSynchronized() { } public int getBuffer() { //加上了共享锁 lock (this) { //判断如果缓冲区内无内容,则Consumer进入wait状态,并且释放对象锁 if (bufferCount == 0) { Console.WriteLine("缓冲区无数据,消费者无法读取"); Monitor.Wait(this); } //Thread.Sleep(1000); int readValue = buffer[readLocation]; //已经从缓冲区读取了内容,所以bufferCount要进行自减. bufferCount--; //求余的目的是为了循环使用缓冲区 readLocation = (readLocation + 1) % buffer.Length; //通知对象的第一个等待线程可以从WaitSleepJoin转换到Started状态. Monitor.Pulse(this); //返回给consumer取出的数值 return readValue; } } //将数据放入缓冲区 public void setBuffer(int writeValue) { //锁住共享数据区 lock (this) { //如果缓冲区已满,那么进入waitsleepjoin状态 if (bufferCount == buffer.Length) { Console.WriteLine("缓冲区满了,等待消费...!"); Monitor.Wait(this); } //Thread.Sleep(1000); //向缓冲区写入数据 buffer[writeLocation] = writeValue; //自加,代表缓冲区现在到底有几个数据 bufferCount++; //用%实现缓冲区的循环利用 writeLocation = (writeLocation + 1) % buffer.Length; //唤醒waitSleepJoin状态的进程,到started状态 Monitor.Pulse(this); //使用lock隐式的释放了共享锁 } } } //生产者类,向缓冲区中放入数据 public class Producer { //定义了同步变量 LetSynchronized shared; //此处构造函数的作用是在启动类中调用Producer的时候,把启动类中定义的sharedLocation传过来 public Producer(LetSynchronized sharedLocation) { shared = sharedLocation; } //定义生产过程 public void produce() { //将数据放入缓冲区 for (int count = 1; count <= 5; count++) { shared.setBuffer(count); Console.WriteLine("生产者向缓冲区中写入 " + count); } //得到当前线程的名字 string name = Thread.CurrentThread.Name; //此线程执行完毕 Console.WriteLine(name + "生产完毕!"); } } //定义消费者类 public class Consumer { private int value; //定义同步变量 LetSynchronized shared; //定义构造函数,负责传递启动类中的shared public Consumer(LetSynchronized sharedLocation) { shared = sharedLocation; } //从缓冲区中循环读取 public void consume() { for (int count = 1; count <= 5; count++) { value = shared.getBuffer(); Console.WriteLine("消费者从缓冲中读取了数据 " + value); } //取得当前线程的名字 string name = Thread.CurrentThread.Name; Console.WriteLine(name + "消费完毕"); } } //设置为启动类 public class ThreadTest { public static void Main() { LetSynchronized shared = new LetSynchronized(); //初始化了生产者和消费者,并且把shared参数传递了过去 Producer producer1 = new Producer(shared); Consumer consumer1 = new Consumer(shared); //定义了一个producerThread线程,new Thread是构造Thread //后面的那个new 则是启动一个新的线程,线程启动的方法是producer1.produce Thread producerThread = new Thread(new ThreadStart(producer1.produce)); producerThread.Name = "生产者"; //同上 Thread consumerThread = new Thread(new ThreadStart(consumer1.consume)); consumerThread.Name = "消费者"; //启动这两个线程 producerThread.Start(); consumerThread.Start(); } }}
上面是代码,加入Thread.Sleep()不会出现问题(程序设置缓冲区个数为1个,可是刚开始生产者生产2个,然后消费者才开始消费),不加Thread.Sleep()运行结果如下:
生产者向缓冲区中写入 1
缓冲区满了,等待消费...!
生产者向缓冲区中写入 2
缓冲区满了,等待消费...!
消费者从缓冲中读取了数据 1
生产者向缓冲区中写入 3
缓冲区满了,等待消费...!
消费者从缓冲中读取了数据 2
生产者向缓冲区中写入 4
缓冲区满了,等待消费...!
消费者从缓冲中读取了数据 3
生产者向缓冲区中写入 5
生产者生产完毕!
消费者从缓冲中读取了数据 4
消费者从缓冲中读取了数据 5
消费者消费完毕
请按任意键继续. . .
高手给解释,小弟万分感谢!
[解决办法]
你的问题是不是输出太有序了?如果是的话,给你一个解释:你的cpu太牛了,你的线程有足够的cpu资源来事情做完,所以他就把事情做到无法继续了才停下。所以这里在输出上看上去很有序,但是你加了延迟类似你主动让线程让出cpu给其他线程,所以从输出上来看你会觉得更像个多线程的输出。
[解决办法]
锁的范围太大了吧,不利于流水线处理