[原创]C#编写的多生产者多消费者同步问题

// 多个生产者和多个消费者,能生产n个产品的情况

using System;
using System.Threading;

public class HoldIntegerSynchronized{

        private int[] buffer;           //缓冲区

        private int occupiedBufferCount = 0;
        
        private int readPosition = 0 , writePosition = 0;
        //下一个读到的位置和写到的位置
        
        public HoldIntegerSynchronized(int capacity){
                buffer = new int[capacity];
        }
        
        public int BufferSize{
                get{
                        return buffer.Length;
                }
        }

        public int Buffer{
                get{
                        int bufferCopy;
                        // 加锁
                        lock(this){
                                while(occupiedBufferCount == 0){        //多个消费者,所以此处改用while
                                        Console.WriteLine(Thread.CurrentThread.Name + " tries to read. ");
                                        DisplayState("Buffer Empty. " + Thread.CurrentThread.Name + " waits.");
                                        Monitor.Wait(this);
                                        // 为临界区之外等待的生产者放行,让他来"生产"
                                        // 一直到生产者生产结束,调用了Monitor.PauseAll()
                                        // 才能继续执行下去,此时,消费者自动重新获得this的锁
                                }

                                --occupiedBufferCount;

                                bufferCopy = buffer[readPosition];

                                readPosition = (readPosition + 1) % buffer.Length;                              
                                
                                DisplayState(Thread.CurrentThread.Name + " reads " + bufferCopy);


                                // 通知,让等待的 生产者线程 进入Started状态,如果生产者处于临界区之外,这句话执行完后他仍然在临界区之外
                                Monitor.PulseAll(this);

                        // 释放锁
                        }//lock
                        return bufferCopy;
                }

                set{
                        // 加锁
                        lock(this){
                                while(occupiedBufferCount == buffer.Length){
                                        Console.WriteLine(Thread.CurrentThread.Name + " tries to write. ");
                                        DisplayState("Buffer Full. " + Thread.CurrentThread.Name + " waits.");
                                        Monitor.Wait(this);    
                                        // 为临界区之外等待消费者放行,让他来"消费"
                                        // 一直到消费者调用了Monitor.Pause()
                                        // 才能继续执行下去,此时,生产者自动重新获得this的锁
                                }

                                buffer[writePosition] = value;
                                
                                ++occupiedBufferCount;
                                
                                writePosition = (writePosition + 1) % buffer.Length;

                                DisplayState(Thread.CurrentThread.Name + " writes " + value);

                                // 通知,让Wait状态的 消费者 进入Started状态,如果消费者处于临界区之外,这句话执行完后他仍然在临界区之外
                                Monitor.PulseAll(this);

                        // 释放锁
                        }
                }
        }

        public void DisplayState(string operation){
                Console.Write("{0,-35}",operation);
                for(int i = 0; i < BufferSize; i++ ){
                        int a = readPosition;
                        int b = writePosition;

                        if( a <= i && i < b) {
                                Console.Write("{0,-9}",buffer[i]);
                        }else if( b < a && !( b <= i && i < a ) ){
                                Console.Write("{0,-9}",buffer[i]);
                        }else if( occupiedBufferCount == BufferSize){
                                Console.Write("{0,-9}",buffer[i]);
                        }else{
                                Console.Write("{0,-9}","");
                        }

                }
                Console.WriteLine("{0}/r/n",occupiedBufferCount);
        }
}

class Producer{
        private HoldIntegerSynchronized sharedLocation;
        private Random randomSleepTime;

        public Producer(HoldIntegerSynchronized shared,Random random){
                sharedLocation = shared;
                randomSleepTime = random;
        }
        
        public void Produce(){
                for (int count=0; count<3; count++)     {
                        Thread.Sleep(randomSleepTime.Next(1,2000));
                        sharedLocation.Buffer = randomSleepTime.Next(5,10);
                }
                Console.WriteLine(Thread.CurrentThread.Name + " done producing./r/nTerminating " + Thread.CurrentThread.Name + "./r/n");
        }
}

class Consumer{
        private HoldIntegerSynchronized sharedLocation;
        private Random randomSleepTime;

        public Consumer(HoldIntegerSynchronized shared,Random random){
                sharedLocation = shared;
                randomSleepTime = random;
        }
        
        public void Consume(){
                int sum = 0;
                for (int count=0; count<4; count++)     {
                        Thread.Sleep(randomSleepTime.Next(1,2000));
                        sum += sharedLocation.Buffer;
                }
                Console.WriteLine(Thread.CurrentThread.Name + " read values totaling:" + sum + "/r/nTerminating " + Thread.CurrentThread.Name + ".");
        }      
}

class SharedCell{
        static void Main(string[] args){
                HoldIntegerSynchronized holdInteger = new HoldIntegerSynchronized(5);
                Random random = new Random();
                        
                Thread[] producerThreads = new Thread[4];
                Thread[] consumerThreads = new Thread[3];

                Console.Write("{0,-35}","Operation");
                for(int i = 0;i < holdInteger.BufferSize;i++){
                        Console.Write("{0,-9}","Elem " + i);
                }
                Console.WriteLine("Occupied Count/r/n");

                for(int i = 0; i < producerThreads.Length;i++){
                        Producer producer = new Producer(holdInteger,random);
                        producerThreads[i] = new Thread(new ThreadStart(producer.Produce));
                        producerThreads[i].Name = "Producer No." + i;
                }

                for(int i = 0; i < consumerThreads.Length;i++){
                        Consumer consumer = new Consumer(holdInteger,random);
                        consumerThreads[i] = new Thread(new ThreadStart(consumer.Consume));
                        consumerThreads[i].Name = "Consumer No." + i;
                }

                for(int i = 0; i < producerThreads.Length;i++){
                        producerThreads[i].Start();
                }

                for(int i = 0; i < consumerThreads.Length;i++){
                        consumerThreads[i].Start();
                }
        }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值