C#线程学习笔记六:线程同步--信号量和互斥体

拈花ヽ惹草 提交于 2019-12-10 23:47:22

    本笔记摘抄自:https://www.cnblogs.com/zhili/archive/2012/07/23/Mutex_And_Semaphore.html,记录一下学习过程以备后续查用。

    一、信号量(Semaphore)

    信号量(Semaphore)是由内核对象维护的int变量。当信号量为0时,在信号量上等待的线程会堵塞;信号量大于0时,就解除堵塞。当在一个信号量上等待

的线程解除堵塞时,内核自动会将信号量的计数减1。在.NET下通过Semaphore类来实现信号量同步。

    Semaphore类限制可同时访问某一资源或资源池的线程数。线程通过调用 WaitOne方法将信号量减1,并通过调用Release方法把信号量加1。

    先说下构造函数:

    public Semaphore(int initialCount,int maximumCount);通过两个参数来设置信号的初始计数和最大计数。

    下面代码演示信号量同步的使用:

    class Program
    {
        //共享资源
        public static int number = 0;
        //初始信号量计数为0,最大计数为10。
        public static Semaphore semaphore = new Semaphore(0, 10);
        static void Main(string[] args)
        {
            #region 线程同步:使用信号量实现同步
            for (int i = 0; i < 10; i++)
            {
                Thread thread = new Thread(new ParameterizedThreadStart(SemaphoreMethod));
                thread.Start(i);
            }

            //每次增加2个信号量,即每次释放2个线程。
            for (int j = 0; j < 5; j++)
            {
                Console.WriteLine("红灯转绿灯……");
                semaphore.Release(2);
                Thread.Sleep(1000);
            }
            Console.Read();
            #endregion
        }

        /// <summary>
        /// Semaphore方法
        /// </summary>
        public static void SemaphoreMethod(object parameter)
        {
            while ((int)parameter != number)
            {
                Thread.Sleep(100);
            }
            //信号量计数减1
            semaphore.WaitOne();
            Console.WriteLine("The current value of number is:{0}", ++number);
        }
    }

    运行结果如下:

    与上一篇AutoResetEvent类似,信号量也可以实现跨进程间的线程同步。通过调用public Semaphore(int initialCount,int maximumCount,string name);构造函数,

传入一个信号量名来实现此功能。

    下面代码演示跨进程间的线程同步:

    第一个进程代码:

    class Program
    {
        //共享资源
        public static int number = 0;
              
        //初始信号量计数为0,最大计数为10。
        public static Semaphore semaphore1 = new Semaphore(0, 10, "Semaphore1");
        public static Semaphore semaphore2 = new Semaphore(0, 10, "Semaphore2");

        static void Main(string[] args)
        {
            #region 线程同步:使用信号量实现跨进程之间的线程同步
            for (int i = 0; i < 10; i++)
            {
                Thread thread = new Thread(new ParameterizedThreadStart(Semaphore1Method));
                thread.Start(i);
            }

            //为了有时间去启动另外一个进程
            Thread.Sleep(15000);

            //每次增加2个信号量,即每次释放2个线程。
            for (int j = 0; j < 5; j++)
            {
                Console.WriteLine("信号灯1红灯转绿灯……");
                semaphore1.Release(2);
                Console.WriteLine("信号灯2红灯转绿灯……");
                semaphore2.Release(2);
                Thread.Sleep(1000);
            }
            Console.Read();
            #endregion
        }

        /// <summary>
        /// Semaphore1方法
        /// </summary>
        public static void Semaphore1Method(object parameter)
        {
            while ((int)parameter != number)
            {
                Thread.Sleep(100);
            }
            //信号量计数减1
            semaphore1.WaitOne();
            Console.WriteLine("Semaphore1:The current value of number is:{0}", ++number);
        }
    }

    第二个进程代码:

    class Program
    {
        //共享资源
        public static int number = 0;
        //创建对象
        public static Semaphore semaphore2 = new Semaphore(0, 10, "Semaphore2");

        static void Main(string[] args)
        {
            #region 通过信号量实现跨进程间的线程同步
            for (int i = 0; i < 10; i++)
            {
                Thread thread = new Thread(new ParameterizedThreadStart(Semaphore2Method));
                thread.Start(i);
            }
            Console.Read();
            #endregion
        }

        /// <summary>
        /// Semaphore2方法
        /// </summary>
        public static void Semaphore2Method(object parameter)
        {
            while ((int)parameter != number)
            {
                Thread.Sleep(100);
            }
            //信号量计数减1
            semaphore2.WaitOne();
            Console.WriteLine("Semaphore2:The current value of number is:{0}", ++number);
        }
    }

    运行结果如下:

    从结果可以看出,第一个进程的semaphore2.Release(2);信号发出后,第二个进程可以收到并释放线程。

    二、互斥体(Mutex)

    Mutex对象是一个同步基元,当某一个线程占用Mutex对象时,其他也需要占用Mutex的线程将处于挂起状态。

    下面代码演示互斥体同步的使用:

    class Program
    {
        //共享资源
        public static int number = 0;
        //互斥体
        public static Mutex mutex = new Mutex();
        
        static void Main(string[] args)
        {
             #region 线程同步:使用互斥体实现同步
            for (int i = 0; i < 10; i++)
            {
                Thread thread = new Thread(MutexMethod);
                thread.Start();
            }

            Console.Read();
            #endregion
        }

        /// <summary>
        /// Mutex方法
        /// </summary>
        public static void MutexMethod(object parameter)
        {
            mutex.WaitOne();
            Thread.Sleep(500);
            Console.WriteLine("The current value of number is:{0}", ++number);
            mutex.ReleaseMutex();
        }
    }

    运行结果如下:

    下面代码演示跨进程间的线程同步:

    第一个进程代码:

    class Program
    {
        //共享资源
        public static int number = 0;
  
        //互斥体
        public static Mutex mutex1 = new Mutex(false, "Mutex1");
        public static Mutex mutex2 = new Mutex(false, "Mutex2");

        static void Main(string[] args)
        {
            #region 线程同步:使用互斥体实现跨进程之间的线程同步
            mutex1.WaitOne();
            mutex2.WaitOne();
            for (int i = 0; i < 10; i++)
            {
                Thread thread = new Thread(new ParameterizedThreadStart(Mutex1Method));
                thread.Start(i);
            }

            //为了有时间去启动另外一个进程
            Thread.Sleep(15000);
            mutex1.ReleaseMutex();
            mutex2.ReleaseMutex();
            Console.Read();
            #endregion
        }

        /// <summary>
        /// Mutex1方法
        /// </summary>
        public static void Mutex1Method(object parameter)
        {
            mutex1.WaitOne();
            Thread.Sleep(500);
            Console.WriteLine("Mutex1:The current value of number is:{0}", ++number);
            mutex1.ReleaseMutex();
        }
    }

    第二个进程代码:

    class Program
    {
        //共享资源
        public static int number = 0;
        //创建对象
        public static Mutex mutex2 = new Mutex(false, "Mutex2");

        static void Main(string[] args)
        {
            #region 通过互斥体实现跨进程之间的线程同步
            for (int i = 0; i < 10; i++)
            {
                Thread thread = new Thread(new ParameterizedThreadStart(Mutex2Method));
                thread.Start(i);
            }
            Console.Read();
            #endregion
        }

        /// <summary>
        /// Mutex2方法
        /// </summary>
        public static void Mutex2Method(object parameter)
        {
            mutex2.WaitOne();
            Thread.Sleep(500);
            Console.WriteLine("Mutex2:The current value of number is:{0}", ++number);
            mutex2.ReleaseMutex();
        }
    }

    运行结果如下:

    从结果可以看出,第一个进程的mutex2.ReleaseMutex();信号发出后,第二个进程可以收到并释放线程。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!