c#中生产者消费者问题

来源:互联网 发布:ubuntu 交叉编译qt 编辑:程序博客网 时间:2024/04/29 01:10


//一个同步程序,生产者向一个缓冲区(定义为三个字节)中写入数据,消费者从中提取数//据,如果缓冲区中没有数据,那么consumer只好wait,进入等待状态,当另一个线程(也就是//生产者)向缓冲区中写入数据猴,执行了Monitor.pulse,唤醒了consumer的等待,开始读取//数据.反之,当producer写入数据的时候,如果缓冲区已满,那么只好进入等待状态,当另一//个线程(也就是消费者)从中读取了数据,缓冲区有了空间,那么消费者执行//Monitor.pulse,唤醒生产者,继续写入数据.//程序使用了lock来锁定共享数据区,而不是使用Monitor.enter和Monitor.exit,因为你可//能很容易忘记enter后exit掉,而lock则是隐式的执行了exit,所以建议用lock.//当然,在程序执行的过程中,因为是线程,所以执行结果是不可再现的!!每次可能执行的顺//序有很多种!! //定义了四个类://第一个类LetSynchronized,主要用来存取数据,并且在存取的时候,加上了共享锁.//第二个类Producer,生产者,调用一个LetSynchronized类的实例的setBuffer方法来存放//数据.//第三个类Consumer,消费者, 调用一个LetSynchronized类的实例的getBuffer方法来存放//数据.//第四个类ThreadStart,测试类,也是这个cs中的启动类,定义了LetSynchornized实例,然//后传递给了Producer和Consumer,然后定义了两个线程,线程启动的是Producer//的produce方法和Consumer的consume方法,最后启动这两个线程. using System;using System.Threading;//LetSynchronized用来存放和取出缓冲区变量public class LetSynchronized{private int[] buffer={-1,-1,-1};//定义了只有三个字节的缓冲区private int bufferCount=0;//确认缓冲区内已放数值的个数private int readLocation=0,writeLocation=0;//确定读写的位置public LetSynchronized(){}public int getBuffer(){lock(this)//加上了共享锁{if(bufferCount==0){Console.WriteLine("缓冲区无数据,消费者无法读取");Monitor.Wait(this);}//判断如果缓冲区内无内容,则Consumer进入wait状态,并且释放对象锁int readValue=buffer[readLocation];bufferCount--;//已经从缓冲区读取了内容,所以bufferCount要进行自减.readLocation=(readLocation+1)%buffer.Length;//求余的目的是为了循环使用缓冲区Monitor.Pulse(this);//通知对象的第一个等待线程可以从WaitSleepJoin转换到Started状态.return readValue;//返回给consumer取出的数值}}public void setBuffer(int writeValue) //将数据放入缓冲区{lock(this){//锁住共享数据区if(bufferCount==buffer.Length){Console.WriteLine("缓冲区!");Monitor.Wait(this);}//如果缓冲区已满,那么进入waitsleepjoin状态buffer[writeLocation]=writeValue;//向缓冲区写入数据bufferCount++;//自加,代表缓冲区现在到底有几个数据writeLocation=(writeLocation+1)%buffer.Length;//用%实现缓冲区的循环利用Monitor.Pulse(this);//唤醒waitSleepJoin状态的进程,到started状态}//使用lock隐式的释放了共享锁}}public class Producer //生产者类,向缓冲区中放入数据{LetSynchronized shared;//定义了同步变量public Producer(LetSynchronized sharedLocation){shared=sharedLocation;}//此处构造函数的作用是在启动类中调用Producer的时候,把启动类中定义的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+"done producing");//此线程执行完毕}}public class Consumer//定义消费者类{private int value;LetSynchronized shared;//定义同步变量public Consumer(LetSynchronized sharedLocation){shared=sharedLocation;}//定义构造函数,负责传递启动类中的sharedpublic void consume(){for(int count=1;count<=5;count++){value=shared.getBuffer();Console.WriteLine("消费者从缓冲中读取了数据 "+value);}//从缓冲区中循环读取string name=Thread.CurrentThread.Name;//取得当前线程的名字Console.WriteLine(name+"done consuming");}}public class ThreadTest //设置为启动类{public static void Main(){LetSynchronized shared=new LetSynchronized();Producer producer1=new Producer(shared);Consumer consumer1=new Consumer(shared);//初始化了生产者和消费者,并且把shared参数传递了过去Thread producerThread = new Thread(new ThreadStart (producer1.produce));producerThread.Name="生产者";//定义了一个producerThread线程,new Thread是构造Thread//后面的那个new 则是启动一个新的线程,线程启动的方法是producer1.produceThread consumerThread = new Thread(new ThreadStart (consumer1.consume));consumerThread.Name="消费者";//同上producerThread.Start();consumerThread.Start();//启动这两个线程} //本文转自:http://hi.baidu.com/wump80/blog/item/f79d92456da67d8ab2b7dcb8.html


原创粉丝点击