c#中生产者消费者问题

[csharp]  view plain copy
  1. //一个同步程序,生产者向一个缓冲区(定义为三个字节)中写入数据,消费者从中提取数  
  2. //据,如果缓冲区中没有数据,那么consumer只好wait,进入等待状态,当另一个线程(也就是  
  3. //生产者)向缓冲区中写入数据猴,执行了Monitor.pulse,唤醒了consumer的等待,开始读取  
  4. //数据.反之,当producer写入数据的时候,如果缓冲区已满,那么只好进入等待状态,当另一  
  5. //个线程(也就是消费者)从中读取了数据,缓冲区有了空间,那么消费者执行  
  6. //Monitor.pulse,唤醒生产者,继续写入数据.  
  7. //程序使用了lock来锁定共享数据区,而不是使用Monitor.enter和Monitor.exit,因为你可  
  8. //能很容易忘记enter后exit掉,而lock则是隐式的执行了exit,所以建议用lock.  
  9. //当然,在程序执行的过程中,因为是线程,所以执行结果是不可再现的!!每次可能执行的顺  
  10. //序有很多种!!  
  11.    
  12. //定义了四个类:  
  13. //第一个类LetSynchronized,主要用来存取数据,并且在存取的时候,加上了共享锁.  
  14. //第二个类Producer,生产者,调用一个LetSynchronized类的实例的setBuffer方法来存放  
  15. //数据.  
  16. //第三个类Consumer,消费者, 调用一个LetSynchronized类的实例的getBuffer方法来存放  
  17. //数据.  
  18. //第四个类ThreadStart,测试类,也是这个cs中的启动类,定义了LetSynchornized实例,然  
  19. //后传递给了Producer和Consumer,然后定义了两个线程,线程启动的是Producer  
  20. //的produce方法和Consumer的consume方法,最后启动这两个线程.  
  21.    
  22. using System;  
  23. using System.Threading;  
  24. //LetSynchronized用来存放和取出缓冲区变量  
  25. public class LetSynchronized  
  26. {  
  27. private int[] buffer={-1,-1,-1};  
  28. //定义了只有三个字节的缓冲区  
  29. private int bufferCount=0;  
  30. //确认缓冲区内已放数值的个数  
  31. private int readLocation=0,writeLocation=0;  
  32. //确定读写的位置  
  33. public LetSynchronized()  
  34. {  
  35. }  
  36. public int getBuffer()  
  37. {  
  38. lock(this)  
  39. //加上了共享锁  
  40. {  
  41. if(bufferCount==0)  
  42. {  
  43. Console.WriteLine("缓冲区无数据,消费者无法读取");  
  44. Monitor.Wait(this);  
  45. }  
  46. //判断如果缓冲区内无内容,则Consumer进入wait状态,并且释放对象锁  
  47. int readValue=buffer[readLocation];  
  48. bufferCount--;  
  49. //已经从缓冲区读取了内容,所以bufferCount要进行自减.  
  50. readLocation=(readLocation+1)%buffer.Length;  
  51. //求余的目的是为了循环使用缓冲区  
  52. Monitor.Pulse(this);  
  53. //通知对象的第一个等待线程可以从WaitSleepJoin转换到Started状态.  
  54. return readValue;  
  55. //返回给consumer取出的数值  
  56. }  
  57. }  
  58. public void setBuffer(int writeValue) //将数据放入缓冲区  
  59. {  
  60. lock(this)  
  61. {//锁住共享数据区  
  62. if(bufferCount==buffer.Length)  
  63. {  
  64. Console.WriteLine("缓冲区!");  
  65. Monitor.Wait(this);  
  66. }  
  67. //如果缓冲区已满,那么进入waitsleepjoin状态  
  68. buffer[writeLocation]=writeValue;  
  69. //向缓冲区写入数据  
  70. bufferCount++;  
  71. //自加,代表缓冲区现在到底有几个数据  
  72. writeLocation=(writeLocation+1)%buffer.Length;  
  73. //用%实现缓冲区的循环利用  
  74. Monitor.Pulse(this);  
  75. //唤醒waitSleepJoin状态的进程,到started状态  
  76. }//使用lock隐式的释放了共享锁  
  77. }  
  78. }  
  79. public class Producer //生产者类,向缓冲区中放入数据  
  80. {  
  81. LetSynchronized shared;  
  82. //定义了同步变量  
  83. public Producer(LetSynchronized sharedLocation)  
  84. {  
  85. shared=sharedLocation;  
  86. }  
  87. //此处构造函数的作用是在启动类中调用Producer的时候,把启动类中定义的sharedLocation传过来  
  88. public void produce()//定义生产过程  
  89. {  
  90. for(int count=1;count<=5;count++)  
  91. {  
  92. shared.setBuffer(count);  
  93. Console.WriteLine("生产者向缓冲区中写入 "+ count);  
  94. }  
  95. //将数据放入缓冲区  
  96. string name=Thread.CurrentThread.Name;  
  97. //得到当前线程的名字  
  98. Console.WriteLine(name+"done producing");  
  99. //此线程执行完毕  
  100. }  
  101. }  
  102. public class Consumer//定义消费者类  
  103. {  
  104. private int value;  
  105. LetSynchronized shared;  
  106. //定义同步变量  
  107. public Consumer(LetSynchronized sharedLocation)  
  108. {  
  109. shared=sharedLocation;  
  110. }  
  111. //定义构造函数,负责传递启动类中的shared  
  112. public void consume()  
  113. {  
  114. for(int count=1;count<=5;count++)  
  115. {  
  116. value=shared.getBuffer();  
  117. Console.WriteLine("消费者从缓冲中读取了数据 "+value);  
  118. }  
  119. //从缓冲区中循环读取  
  120. string name=Thread.CurrentThread.Name;  
  121. //取得当前线程的名字  
  122. Console.WriteLine(name+"done consuming");  
  123. }  
  124. }  
  125. public class ThreadTest //设置为启动类  
  126. {  
  127. public static void Main()  
  128. {  
  129. LetSynchronized shared=new LetSynchronized();  
  130. Producer producer1=new Producer(shared);  
  131. Consumer consumer1=new Consumer(shared);  
  132. //初始化了生产者和消费者,并且把shared参数传递了过去  
  133. Thread producerThread = new Thread(new ThreadStart (producer1.produce));  
  134. producerThread.Name="生产者";  
  135. //定义了一个producerThread线程,new Thread是构造Thread  
  136. //后面的那个new 则是启动一个新的线程,线程启动的方法是producer1.produce  
  137. Thread consumerThread = new Thread(new ThreadStart (consumer1.consume));  
  138. consumerThread.Name="消费者";  
  139. //同上  
  140. producerThread.Start();  
  141. consumerThread.Start();  
  142. //启动这两个线程  
  143. }  
  144.    
  145. //本文转自:http://hi.baidu.com/wump80/blog/item/f79d92456da67d8ab2b7dcb8.html  
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值