[.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,如需转载请自行联系原作者



相关文章
|
1月前
|
安全 Java
深入Java并发编程:线程同步与互斥机制
【4月更文挑战第6天】Java并发编程中,确保数据一致性与防止条件竞争是关键。语言提供`synchronized`关键字、`Lock`接口和原子变量等机制处理并发问题。线程同步问题包括竞态条件、死锁和活锁。`synchronized`实现内置锁,`Lock`接口提供更灵活的锁管理,原子变量则支持无锁安全操作。理解并恰当使用这些工具能有效管理并发,避免数据不一致。
|
1月前
|
消息中间件 安全 Linux
线程同步与IPC:单进程多线程环境下的选择与权衡
线程同步与IPC:单进程多线程环境下的选择与权衡
78 0
|
1月前
|
Linux API C++
c++多线程——互斥锁
c++多线程——互斥锁
|
12天前
|
开发框架 监控 Java
【.NET Core】多线程之线程池(ThreadPool)详解(二)
【.NET Core】多线程之线程池(ThreadPool)详解(二)
30 3
|
12天前
|
SQL 开发框架 Java
【.NET Core】多线程之线程池(ThreadPool)详解(一)
【.NET Core】多线程之线程池(ThreadPool)详解(一)
22 2
|
12天前
|
算法 安全 Java
【.NET Core】 多线程之(Thread)详解
【.NET Core】 多线程之(Thread)详解
19 1
|
17天前
|
安全 C++
线程同步:互斥与条件变量
线程同步:互斥与条件变量
|
24天前
|
安全 算法 Linux
【Linux 系统】多线程(线程控制、线程互斥与同步、互斥量与条件变量)-- 详解(下)
【Linux 系统】多线程(线程控制、线程互斥与同步、互斥量与条件变量)-- 详解(下)
|
24天前
|
存储 Linux 程序员
【Linux 系统】多线程(线程控制、线程互斥与同步、互斥量与条件变量)-- 详解(中)
【Linux 系统】多线程(线程控制、线程互斥与同步、互斥量与条件变量)-- 详解(中)
|
24天前
|
缓存 Linux 调度
【Linux 系统】多线程(线程控制、线程互斥与同步、互斥量与条件变量)-- 详解(上)
【Linux 系统】多线程(线程控制、线程互斥与同步、互斥量与条件变量)-- 详解(上)