读书人

【跪求】用C#写的生产者-消费者 出了有

发布时间: 2011-12-28 22:45:21 作者: rapoo

【跪求】用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给其他线程,所以从输出上来看你会觉得更像个多线程的输出。
[解决办法]
锁的范围太大了吧,不利于流水线处理

读书人网 >C#

热点推荐