zoukankan      html  css  js  c++  java
  • C#线程学习笔记六:线程同步--信号量和互斥体

        本笔记摘抄自: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();信号发出后,第二个进程可以收到并释放线程。

  • 相关阅读:
    Flask上下文管理及源码刨析
    Python数据库连接池DBUtils
    装饰器的修复wraps,偏函数partial 以及chain
    unity官方案例精讲(第三章)--星际航行游戏Space Shooter
    c#多态性
    C# 继承
    c#类(class)
    一、事件函数的执行顺序(脚本的生命周期)
    一、Vuforia_AR
    四、其它(一)
  • 原文地址:https://www.cnblogs.com/atomy/p/12004206.html
Copyright © 2011-2022 走看看