• c#中的多线程同步


    在处理多线程同步问题的时候,我们一般有临界区,互斥量,信号量和消息机制等几种解决方案,在c#中可以非常方便的使用它们来实现进程的同步。下面我就常用的lock,Monitor和Mutex几种来说明如何实现进程的同步。

        lock和Monitor依靠一种“令牌”对象来实现进程的同步,下面看一段示范代码:

       class Example
        {
            int count = 0;
            object o = new object();//令牌对象
            static void Main(string[] args)
            {
                Example e=new Example();
                Thread pthread = new Thread(e.produce);
                Thread cthread = new Thread(e.consume);

                pthread.Start();

                cthread.Start();

            }
            public void produce()
            {
                while (true)
                {
                    lock (o)
                    {
                        count = count + 1;
                    }
                }
            }
            public void consume()
            {
                while (true)
                {
                    lock (o)
                    {
                        count = count - 1;
                    }
                }
            }
        }

            在程序中,我们需要产生两个生产和消费的线程,但是两个线程对count的访问必须是互斥的,也就是要实现两个现场的同步。在上面的代码中,首先实例化一个令牌对象o,当需要操作互斥变量count的时候,我就用lock关键字去取令牌,如果此时令牌可以拿到,就执行对count的操作,然后释放令牌。如果此时令牌在另外一个线程手里,就等待知道该令牌被释放。Monitor的使用与lock很相似,下面附上使用代码,不再另加说明:

          Monitor.Enter(o);

          count=count+1;

          Monitor.Exit(o);

            Mutex是使用互斥的机制来实现进程的同步,Mutex不需要使用额外的令牌对象。下面是用Mutex来解决著名的生产者消费者问题,设定消费者和生产者各3个,公共区容量为5,生产100个,下面看代码:

             class Program
        {
            static void Main(string[] args)
            {
                ProduceAndConsume pac=new ProduceAndConsume();
                Thread pthread1 = new Thread(pac.produce);
                Thread pthread2 = new Thread(pac.produce);
                Thread pthread3 = new Thread(pac.produce);
                Thread cthread1 = new Thread(pac.consume);
                Thread cthread2 = new Thread(pac.consume);
                Thread cthread3 = new Thread(pac.consume);
                pthread1.Start();
                pthread2.Start();
                pthread3.Start();
                cthread1.Start();
                cthread2.Start();
                cthread3.Start();
            }
        }
        class ProduceAndConsume
        {
            private int count = 0;
            private int pID=0;
            private int cID = 0;
            private object mutexobjext = new object();
            private Mutex IDmux = new Mutex();//该互斥量是对产品序号的互斥
            private Mutex Countmux = new Mutex();//该互斥量是对公共区产品数量的互斥
            public void produce()
            {
                while (true)
                {
                    IDmux.WaitOne();//申请产品序号互斥,不行则等待
                    if (pID >= 100)
                    {

                        //达到一百个,释放互斥,线程结束
                        IDmux.ReleaseMutex();
                        break;
                    }
                    Countmux.WaitOne();//申请公共区数量互斥
                    if (count >= 5)
                    {

                        //公共区满,生产线程释放互斥后睡眠
                        Countmux.ReleaseMutex();
                        IDmux.ReleaseMutex();
                        Thread.Sleep(2);
                        continue;
                    }
                    else
                    {

                           //公共区数量加一,并打印生产产品的序号信息,完成后释放互斥
                            count = count + 1;
                            Countmux.ReleaseMutex();
                            pID = pID + 1;
                            Console.WriteLine("Has produced {0}..", pID);
                            IDmux.ReleaseMutex();
                            Thread.Sleep(1);
                    }
                }
            }
            public void consume()
            {

                //类似于produce(),不同是消费过程
                while (true)
                {
                    IDmux.WaitOne();
                    if(cID>=100)
                    {
                        IDmux.ReleaseMutex();
                        break;
                    }
                    Countmux.WaitOne();
                    if (count <= 0)
                    {
                        Countmux.ReleaseMutex();
                        IDmux.ReleaseMutex();
                        Thread.Sleep(2);
                        continue;
                    }
                    else
                    {
                            count = count - 1;
                            Countmux.ReleaseMutex();
                            cID = cID + 1;
                            Console.WriteLine("Has Consume {0}", cID);
                            IDmux.ReleaseMutex();
                            Thread.Sleep(1);
                    }
                }
            }
        }

          下面是执行结果,可以看到进程已经很好的同步了 :

    Has produced 1..
    Has produced 2..
    Has produced 3..
    Has produced 4..
    Has produced 5..
    Has Consume 1
    Has produced 6..
    Has Consume 2
    Has Consume 3
    Has Consume 4
    Has produced 7..
    Has Consume 5
    Has Consume 6
    Has produced 8..
    Has produced 9..
    Has Consume 7
    Has produced 10..
    Has Consume 8
    Has Consume 9
    Has Consume 10
    Has produced 11..
    Has produced 12..
    Has Consume 11
    Has produced 13..
    Has produced 14..
    Has produced 15..
    Has Consume 12
    Has produced 16..
    Has Consume 13
    Has Consume 14
    Has produced 17..
    Has produced 18..
    Has Consume 15
    Has produced 19..
    Has Consume 16
    Has produced 20..
    Has Consume 17
    Has produced 21..
    Has produced 22..
    Has Consume 18
    Has Consume 19
    Has Consume 20
    Has produced 23..
    Has Consume 21
    Has Consume 22
    Has produced 24..
    Has Consume 23
    Has produced 25..
    Has produced 26..
    Has Consume 24
    Has produced 27..
    Has Consume 25
    Has Consume 26
    Has produced 28..
    Has Consume 27
    Has Consume 28
    Has produced 29..
    Has produced 30..
    Has Consume 29
    Has produced 31..
    Has Consume 30
    Has Consume 31
    Has produced 32..
    Has Consume 32
    Has produced 33..
    Has produced 34..
    Has produced 35..
    ..................................

  • 相关阅读:
    说说渐进式增强
    Websocket模板
    Echart图表显示单位
    JS配置文件设置,共享变量抽取
    PHP处理字符串的10个简单方法
    C#实现只许一个实例运行(使用mutex类)
    实现PHP基本安全11条
    PHP开发不能违背的安全规则
    Querying a motor position
    log info
  • 原文地址:https://www.cnblogs.com/yibinboy/p/1633077.html
Copyright © 2020-2023  润新知