日期:2014-05-18  浏览次数:21047 次

【跪求】用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 Threa