[.Net线程处理系列]专题六:线程同步——信号量和互斥体

简介:

也不多说了,直接进入主题了

一、信号量(Semaphore)

信号量(Semaphore)是由内核对象维护的int变量,当信号量为0时,在信号量上等待的线程会堵塞,信号量大于0时,就解除堵塞。当在一个信号量上等待的线程解除堵塞时,内核自动会将信号量的计数减1。在.net 下通过Semaphore类来实现信号量同步。

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

先说下构造函数:

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

下面通过一段代码来演示信号量同步的使用:

 

  
  
  1. class Program  
  2.     {  
  3.         // 初始信号量计数为0,最大计数为10  
  4.         public static Semaphore semaphore =new Semaphore(0,10);  
  5.         public static int time = 0;  
  6.         static void Main(string[] args)  
  7.         {  
  8.             for (int i = 0; i < 5; i++)  
  9.             {  
  10.                 Thread test = new Thread(new ParameterizedThreadStart(TestMethod));  
  11.  
  12.                 // 开始线程,并传递参数  
  13.                 test.Start(i);  
  14.             }  
  15.  
  16.             // 等待1秒让所有线程开始并阻塞在信号量上  
  17.             Thread.Sleep(500);  
  18.  
  19.             // 信号量计数加4  
  20.             // 最后可以看到输出结果次数为4次  
  21.             semaphore.Release(4);  
  22.             Console.Read();           
  23.         }  
  24.  
  25.         public static void TestMethod(object number)  
  26.         {  
  27.             // 设置一个时间间隔让输出有顺序  
  28.             int span = Interlocked.Add(ref time, 100);  
  29.             Thread.Sleep(1000 + span);  
  30.  
  31.             //信号量计数减1  
  32.             semaphore.WaitOne();  
  33.               
  34.             Console.WriteLine("Thread {0} run ", number);  
  35.         }  
  36.     } 
运行结果:

 同样信号量也可以实现进程中线程的同步,同样也是通过对信号量命名来实现的,

通过调用public Semaphore(int initialCount,int maximumCount,string name);该构造函数多传入一个信号量名来实现

下面一段实例代码来演示下:


 
 
  1. using System;  
  2. using System.Threading;  
  3.  
  4. namespace SemaphoreSample  
  5. {  
  6.     class Program  
  7.     {  
  8.         // 初始信号量计数为4,最大计数为10  
  9.         public static Semaphore semaphore =new Semaphore(4,10,"My");  
  10.         public static int time = 0;  
  11.         static void Main(string[] args)  
  12.         {  
  13.             for (int i = 0; i < 3; i++)  
  14.             {  
  15.                 Thread test = new Thread(new ParameterizedThreadStart(TestMethod));  
  16.  
  17.                 // 开始线程,并传递参数  
  18.                 test.Start(i);  
  19.             }  
  20.  
  21.             // 等待1秒让所有线程开始并阻塞在信号量上  
  22.             Thread.Sleep(1000);  
  23.  
  24.             Console.Read();           
  25.         }  
  26.  
  27.         public static void TestMethod(object number)  
  28.         {  
  29.             // 设置一个时间间隔让输出有顺序  
  30.             int span = Interlocked.Add(ref time, 500);  
  31.             Thread.Sleep(1000 + span);  
  32.  
  33.             //信号量计数减1  
  34.             semaphore.WaitOne();  
  35.               
  36.             Console.WriteLine("Thread {0} run ", number);  
  37.         }  
  38.     }  
 

运行结果:

    从运行结果中可以看出, 第二个进程值运行了一行语句, 因为我们设置的初始信号计数为4,每运行一个线程,信号计数通过调用WaitOne方法减1,所以第二个进行一开始信号计数为1而不是进程一中的4,如果我们把信号计数后面的name参数去除的话,此时第二个进程和第一个进程中的结果应该是一样的(因为此时没有进行不同进程中线程的同步)。

二、互斥体(Mutex)

同样互斥体也是同样可以实现线程之间的同步和不同进程中线程的同步的

先看看线程之间的同步的例子吧(在这里我也不多做解释了,因为他们之间的使用很类似,直接贴出代码):


 
 
  1. class Program  
  2.     {  
  3.         public static Mutex mutex = new Mutex();  
  4.         public static int count;  
  5.  
  6.         static void Main(string[] args)  
  7.         {  
  8.             for (int i = 0; i < 10; i++)  
  9.             {  
  10.                 Thread test = new Thread(TestMethod);  
  11.  
  12.                 // 开始线程,并传递参数  
  13.                 test.Start();  
  14.             }  
  15.  
  16.             Console.Read();  
  17.         }  
  18.  
  19.         public static void TestMethod()  
  20.         {  
  21.             mutex.WaitOne();  
  22.             Thread.Sleep(500);  
  23.             count++;  
  24.             Console.WriteLine("Current Cout Number is {0}", count);  
  25.             mutex.ReleaseMutex();  
  26.         }  
  27.     } 
 
 

运行结果:

 实现进程间同步:


 
 
  1. class Program  
  2.     {  
  3.         public static Mutex mutex = new Mutex(false,"My");  
  4.  
  5.         static void Main(string[] args)  
  6.         {  
  7.             Thread t = new Thread(TestMethod);  
  8.             t.Start();  
  9.  
  10.             Console.Read();  
  11.         }  
  12.  
  13.         public static void TestMethod()  
  14.         {  
  15.             mutex.WaitOne();  
  16.             Thread.Sleep(5000);  
  17.             Console.WriteLine("Method start at : " + DateTime.Now.ToLongTimeString());  
  18.             mutex.ReleaseMutex();  
  19.         }  
  20.     } 
 
运行结果:

    从运行结果看出两个进程之间的时间间隔为5秒,当我们把构造函数中命名参数去掉时就可以看出差别了。


 三、小结

    到这里多线程处理基本上讲完,这个系列也只是一个入门,真真要好好掌握多线程,还是要在项目中多去实战的。接下来我可能会做一个小的例子的,大概的思路是实现一个文件的下载的这样的例子。如果大家有什么好的例子来运用多线程的知识的话,可以留言给我,我也会尽量去实现(如果不会的话,这样也可以促使我去学习),实现后也会和大家分享的。

 




     本文转自LearningHard 51CTO博客,原文链接:http://blog.51cto.com/learninghard/1034793,如需转载请自行联系原作者



相关文章
|
17天前
|
供应链 安全 NoSQL
PHP 互斥锁:如何确保代码的线程安全?
在多线程和高并发环境中,确保代码段互斥执行至关重要。本文介绍了 PHP 互斥锁库 `wise-locksmith`,它提供多种锁机制(如文件锁、分布式锁等),有效解决线程安全问题,特别适用于电商平台库存管理等场景。通过 Composer 安装后,开发者可以利用该库确保在高并发下数据的一致性和安全性。
30 6
|
24天前
|
开发框架 Java .NET
.net core 非阻塞的异步编程 及 线程调度过程
【11月更文挑战第12天】本文介绍了.NET Core中的非阻塞异步编程,包括其基本概念、实现方式及应用示例。通过`async`和`await`关键字,程序可在等待I/O操作时保持线程不被阻塞,提高性能。文章还详细说明了异步方法的基础示例、线程调度过程、延续任务机制、同步上下文的作用以及如何使用`Task.WhenAll`和`Task.WhenAny`处理多个异步任务的并发执行。
|
2月前
|
安全 Java 开发者
在多线程编程中,确保数据一致性与防止竞态条件至关重要。Java提供了多种线程同步机制
【10月更文挑战第3天】在多线程编程中,确保数据一致性与防止竞态条件至关重要。Java提供了多种线程同步机制,如`synchronized`关键字、`Lock`接口及其实现类(如`ReentrantLock`),还有原子变量(如`AtomicInteger`)。这些工具可以帮助开发者避免数据不一致、死锁和活锁等问题。通过合理选择和使用这些机制,可以有效管理并发,确保程序稳定运行。例如,`synchronized`可确保同一时间只有一个线程访问共享资源;`Lock`提供更灵活的锁定方式;原子变量则利用硬件指令实现无锁操作。
27 2
|
2月前
|
运维 API 计算机视觉
深度解密协程锁、信号量以及线程锁的实现原理
深度解密协程锁、信号量以及线程锁的实现原理
43 1
|
2月前
|
安全 Linux
Linux线程(十一)线程互斥锁-条件变量详解
Linux线程(十一)线程互斥锁-条件变量详解
|
3月前
|
Java 数据中心 微服务
Java高级知识:线程池隔离与信号量隔离的实战应用
在Java并发编程中,线程池隔离与信号量隔离是两种常用的资源隔离技术,它们在提高系统稳定性、防止系统过载方面发挥着重要作用。
58 0
|
4月前
|
安全 C++
利用信号量实现线程顺序执行
【8月更文挑战第25天】信号量是多线程编程中用于控制共享资源访问的关键同步机制,能有效保证线程按预设顺序执行。实现方法包括:引入相关头文件(如 C++ 中的 `&lt;semaphore.h&gt;`),创建信号量并通过 `sem_init` 设置初始值;在各线程函数中运用 `sem_post` 与 `sem_wait` 来传递执行权;最后,通过 `sem_destroy` 销毁信号量以释放资源。使用过程中需注意错误处理、确保线程安全及合理设定信号量初值,以维持程序稳定性和高效性。
|
4月前
利用信号量实现线程顺序执行
【8月更文挑战第24天】本文介绍了如何运用信号量确保多线程程序中线程按预定顺序执行的方法。信号量作为同步机制,可有效控制共享资源访问,防止数据不一致。实现步骤包括:引入必要的头文件(如 `&lt;pthread.h&gt;` 和 `&lt;semaphore.h&gt;`),定义信号量变量(如 `sem_t` 类型),初始化信号量(通常第一个信号量设为1,其余设为0),以及创建线程(每个线程执行特定任务并释放相应信号量)。
|
4月前
|
Java
多线程线程同步
多线程的锁有几种方式
|
4月前
|
数据采集 Java Python
python 递归锁、信号量、事件、线程队列、进程池和线程池、回调函数、定时器
python 递归锁、信号量、事件、线程队列、进程池和线程池、回调函数、定时器