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

摘要:
当一个等待信号量的线程被解除阻塞时,内核会自动将信号量计数减去1.At NET,以通过信号量类实现信号量同步。线程通过调用WaitOne方法将信号量减少1,并通过调用Release方法将信号增加1。以下代码演示了跨进程线程同步:第一个进程代码:classProgram{//shared resource publicstaticintnumber=0;//初始信号量计数为0,最大计数为10。publicstaticSemaphore1=newSemaphore;publicstaticSemaphore2=newSemamphore;staticvoidMain{#region线程同步:使用信号量实现{Threadhread=newThread;Thread.Start;}//的跨进程线程同步为了有时间启动另一个进程,线程。Sleep//每次增加2个信号量,即每次释放2个线程。

    本笔记摘抄自: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#线程学习笔记六:线程同步--信号量和互斥体第1张

    与上一篇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#线程学习笔记六:线程同步--信号量和互斥体第2张

    从结果可以看出,第一个进程的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#线程学习笔记六:线程同步--信号量和互斥体第3张

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

    第一个进程代码:

    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#线程学习笔记六:线程同步--信号量和互斥体第4张

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

免责声明:文章转载自《C#线程学习笔记六:线程同步--信号量和互斥体》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇spring boot 支持返回 xmlJNA结构体嵌套如何调用下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Python thread &amp;amp; process

线程 点击查看 <- 进程 点击查看 <- 线程与进程的区别 线程共享内部空间;进程内存空间独立 同一个进程的线程之间可以直接交流;两个进程之间想通信必须通过一个中间代理 创建新线程很简单,占用资源较少;创建新进程是对父进程的克隆,会占用很多资源 一个线程可以控制和操作同一进程里的其他线程;但是进程只能操作子进程 修改父线程可能会影响到进程下...

【java虚拟机】jvm内存模型

作者:pengjunlee原文链接:https://blog.csdn.net/pengjunlee/article/details/71909239 目录 一、运行时数据区域   1、程序计数器   2、Java 虚拟机栈   3、本地方法栈   4、Java 堆   5、方法区   6、运行时常量池   7、直接内存 二、OutOfMemoryErro...

Jmeter(三十三)Stepping Thread Group

  碰巧最近在做性能测试,就记一下Jmeter的第三方插件Stepping Thread Group。   具体一些插件信息,可以去:jmeter-plugins.org去进行下载。   该插件目前是已经被弃用的。不过得益于它良好的一些界面指标,加压方式仍可选择。      横坐标和纵坐标分别是:运行时间和线程数。   本图是“2s启动一个线程”的例子。...

内存管理[3]堆

VirtualAlloc 分配的内存是以 4K 为最小单位、连续的内存地址(但映射到真实的内存时它不一定是连续的), 前面说了, 它不适合分配小内存(譬如只有几个字节的变量); 局部的变量在 "栈" 中有程序自动管理, 那么那些全局的小变量怎么办呢? 这就要用到 "堆".这样看来, VirtualAlloc 分配的内存既不是 "栈" 也不是 "堆"; Vi...

C#中的Thread.IsBackground的琢磨

今天在执行一段前后台线程的时候,发现了我把线程全部都设置成了后台线程IsBackground = true,但是还是会执行后台线程,一直执行完后台线程。 代码如下: usingSystem; usingSystem.Collections.Generic; usingSystem.Linq; usingSystem.Linq.Expressions; us...

Linux-pthread如何设置线程的优先级

设置线程优先级的函数: int pthread_setschedparam(pthread_t target_thread, int policy, const struct sched_param *param) 它主要用于设置线程的调用策略和优先级。 参数说明: 1.  target_thread是使用pthread_create所获得的线程ID。  ...