欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-05-18 15:38:57
本笔记摘抄自:https://www.cnblogs.com/zhili/archive/2012/07/23/Mutex_And_Semaphore.html,记录一下学习过程以备后续查用。 一、信号量(Semaphore) 信号量(Semaphore)是由内核对象维护的int变量。当信号量为0时 ......

    本笔记摘抄自: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); } }

    运行结果如下:

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

    与上一篇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);
        }
    }

    运行结果如下:

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

    从结果可以看出,第一个进程的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();
        }
    }

    运行结果如下:

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

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

    第一个进程代码:

    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();
        }
    }

    运行结果如下:

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

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