今天整理“信号量”的相关知识,其实想想也蛮有趣的,锁,互斥,信号量都可以实现线程同步,在framework里面主要有三种。
<1>:ManualResetEvent
<2>:AutoResetEvent
<3>: Semaphore
好,下面就具体看看这些玩意的使用。
一:ManualResetEvent
该对象有两种信号量状态True和False,好奇的我们肯定想知道True和False有什么区别,稍后的例子见分晓,有三个方法值得学习一下。
1:WaitOne
该方法用于阻塞线程,默认是无限期的阻塞,有时我们并不想这样,而是采取超时阻塞的方法,如果超时就放弃阻塞,这样也就避免了无限期
等待的尴尬。
2:Set
手动修改信号量为True,也就是恢复线程执行。
3:ReSet
手动修改信号量为False,暂停线程执行。
好了,下面举个例子说明一下。
<1> 信号量初始为False,WaitOne采用无限期阻塞,可以发现线程间可以进行交互。
1 public class Example
2 {
3 public static void Main()
4 {
5 Thread t = new Thread(Run);
6
7 t.Name = "Jack";
8
9 Console.WriteLine("当前时间:{0} {1} {1},我是主线程,收到请回答。", DateTime.Now, t.Name);
10
11 t.Start();
12
13 Thread.Sleep(5000);
14
15 mr.Set();
16
17 Console.Read();
18 }
19
20 static ManualResetEvent mr = new ManualResetEvent(false);
21
22 static void Run()
23 {
24 mr.WaitOne();
25
26 Console.WriteLine("\n当前时间:{0} 主线程,主线程,{1}已收到!", DateTime.Now, Thread.CurrentThread.Name);
27 }
28 }
<2> 信号量初始为True,WaitOne采用无限期阻塞,实验发现WaitOne其实并没有被阻塞。
static ManualResetEvent mr = new ManualResetEvent(true);
<3>信号量初始为False,WaitOne采用超时2s,虽然主线程要等5s才能进行Set操作,但是WaitOne已经等不及提前执行了。
1 public class Example
2 {
3 public static void Main()
4 {
5 Thread t = new Thread(Run);
6
7 t.Name = "Jack";
8
9 Console.WriteLine("当前时间:{0} {1} {1},我是主线程,收到请回答。", DateTime.Now, t.Name);
10
11 t.Start();
12
13 Thread.Sleep(5000);
14
15 mr.Set();
16
17 Console.Read();
18 }
19
20 static ManualResetEvent mr = new ManualResetEvent(false);
21
22 static void Run()
23 {
24 mr.WaitOne(2000);
25
26 Console.WriteLine("\n当前时间:{0} 主线程,主线程,{1}已收到!", DateTime.Now, Thread.CurrentThread.Name);
27 }
28 }
二:AutoResetEvent
在VS对象浏览器中,我们发现AutoResetEvent和ManualResetEvent都是继承于EventWaitHandle,所以基本功能是一样的,不过值得注意
的一个区别是WaitOne会改变信号量的值,比如说初始信号量为True,如果WaitOne超时信号量将自动变为False,而ManualResetEvent则不会。
1 public class Example
2 {
3 public static void Main()
4 {
5 Thread t = new Thread(Run);
6
7 t.Name = "Jack";
8
9 t.Start();
10
11 Console.Read();
12 }
13
14 static AutoResetEvent ar = new AutoResetEvent(true);
15
16 static void Run()
17 {
18 var state = ar.WaitOne(1000, true);
19
20 Console.WriteLine("我当前的信号量状态:{0}", state);
21
22 state = ar.WaitOne(1000, true);
23
24 Console.WriteLine("我恨你,不理我,您现在的状态是:{0}", state);
25
26 }
27 }
三:Semaphore
这玩意是.net 4.0新增的,用于控制线程的访问数量,默认的构造函数为initialCount和maximumCount,表示默认设置的信号量个数和
最大信号量个数,其实说到底,里面是采用计数器来来分配信号量,当你WaitOne的时候,信号量自减,当Release的时候,信号量自增,然而
当信号量为0的时候,后续的线程就不能拿到WaitOne了,所以必须等待先前的线程通过Release来释放。
好了,下面还是举例子来说明一下:
<1> initialCount=1,maximunCount=10,WaitOne采用无限期等待。
1 namespace ConsoleApplication3
2 {
3 class Program
4 {
5 static void Main(string[] args)
6 {
7
8 Thread t1 = new Thread(Run1);
9 t1.Start();
10
11 Thread t2 = new Thread(Run2);
12 t2.Start();
13
14 Console.Read();
15 }
16
17 static Semaphore sem = new Semaphore(1, 10);
18
19 static void Run1()
20 {
21 sem.WaitOne();
22
23 Console.WriteLine("大家好,我是Run1");
24 }
25
26 static void Run2()
27 {
28 sem.WaitOne();
29
30 Console.WriteLine("大家好,我是Run2");
31 }
32 }
33 }
我们悲剧的发现t2线程不能执行,我们知道WaitOne相当于自减信号量,然而默认的信号量个数为1,所以t2想执行必须等待t1通过Release来释放。
1 static void Run1()
2 {
3 sem.WaitOne();
4
5 Console.WriteLine("大家好,我是Run1");
6
7 sem.Release();
8 }
可能有的同学要问,我不是设置了maximunCount=10吗?为什么没有起到作用?是的,默认情况下是没有起到作用,必须要我们手动干预一下,
我们知道调用Release方法相当于自增一个信号量,然而Release有一个重载,可以指定自增到maximunCount个信号量,这里我就在主线程上
Release(10),看看效果。
1 namespace ConsoleApplication3
2 {
3 class Program
4 {
5 static void Main(string[] args)
6 {
7
8 Thread t1 = new Thread(Run1);
9 t1.Start();
10
11 Thread t2 = new Thread(Run2);
12 t2.Start();
13
14 Thread.Sleep(1000);
15
16 sem.Release(10);
17
18 Console.Read();
19 }
20
21 static Semaphore sem = new Semaphore(1, 10);
22
23 static void Run1()
24 {
25 sem.WaitOne();
26
27 Console.WriteLine("大家好,我是Run1");
28 }
29
30 static void Run2()
31 {
32 sem.WaitOne();
33
34 Console.WriteLine("大家好,我是Run2");
35 }
36 }
37 }
<2> Semaphore命名,升级进程交互。
在VS对象浏览器中发现Semaphore是继承字WaitHandle,而WaitHandle封装了win32的一些同步机制,所以当我们给Semaphore命名的时候
就会在系统中可见,下面举个例子,把下面的代码copy一份,运行两个程序。
1 namespace ConsoleApplication3
2 {
3 class Program
4 {
5 static void Main(string[] args)
6 {
7
8 Thread t1 = new Thread(Run1);
9 t1.Start();
10
11 Thread t2 = new Thread(Run2);
12 t2.Start();
13
14 Console.Read();
15 }
16
17 static Semaphore sem = new Semaphore(3, 10, "cnblogs");
18
19 static void Run1()
20 {
21 sem.WaitOne();
22
23 Console.WriteLine("当前时间:{0} 大家好,我是Run1", DateTime.Now);
24 }
25
26 static void Run2()
27 {
28 sem.WaitOne();
29
30 Console.WriteLine("当前时间:{0} 大家好,我是Run2", DateTime.Now);
31 }
32 }
33 }
是的,我设置了信号量是3个,所以只能有三个线程持有WaitOne,后续的线程只能苦苦的等待。
分享到:
相关推荐
Parallel的使用 多线程系列(5)5天不再惧怕多线程——第五天 线程池 5天不再惧怕多线程——第四天 信号量 5天不再惧怕多线程——第三天 互斥体 5天不再惧怕多线程——第二天 锁机制 5天不再惧怕多线程——第一天 尝试...
采用QT5开发的多线程同步,包括信号量,互斥量,等待条件等,里面包含多个生产者,一个消费者。如需多个消费者,可直接复制粘贴进行模拟。
java上机报告5——Java的多线程编程1
Qt5多线程,使用QSemaphore类实现生产者和消费者问题。
QT6之多线程控制-互斥量和信号量
* 支持多线程,保证获取到的连接一定是没有被其他线程正在使用 * 按需创建连接,可以创建多个连接,可以控制连接的数量 * 连接被复用,不是每次都重新创建一个新的连接(连接的创建是一个很消耗资源的过程) * ...
信号与系统第四版答案——吴大正.信号与线性系统第四版答案——吴大正.
a: 创建一个线程 b: 创建多个线程 c: 多线程访问同一资源 d: 经典线程同步互斥问题 e: 使用关键段解决子线程互斥问题 f: 利用事件实现线程同步问题 ...I: 信号量 semaphore 解决线程同步问题
Python爬虫编程基础5天速成——P13——文件处理(csdn)————程序
四、Win32 API多线程编程例程 4 例程1 MultiThread1 4 例程2 MultiThread2 5 例程3 MultiThread3 6 例程4 MultiThread4 9 多线程编程之二——MFC中的多线程开发 11 五、MFC对多线程编程的支持 11 六、MFC多线程编程...
PyQt5自学记录(1)——PyQt5中多线程实现详解 最近想用PyQt5完成图像识别的一个GUI系统,在调用算法模型进行识别的时候,界面会卡住没有反应,所以想学习一下多线程解决这个问题。然后。。。发现没有基础学习来确实...
定义一个被多线程调用的函数4.定义一个多线程函数5.完整代码 1.实现的功能 代码实现功能,将数据列表中的数据传入,使用四个线程处理,将结果保存在Queue中,线程执行完后,从Queue中获取存储的结果 2.导入线程,队列...
第1章 Single Threaded Execution——能通过这座桥的,只有一个人 第2章 Immutable——想破坏它也没办法 第3章 Guarded Suspension——要等到我准备好喔 第4章 Balking——不需要的话,就算了吧 第5章 Producer-...
第4次-3(第5章 单元测试和集成测试——集成测试第4次-3(第5章 单元测试和集成测试——集成测试第4次-3(第5章 单元测试和集成测试——集成测试第4次-3(第5章 单元测试和集成测试——集成测试第4次-3(第5章 单元...
操作系统初学,关于信号量同步的实验报告,用三种方法避免哲学家进餐问题死锁,a:and信号量,b:控制进餐人数,c设置条件
Java多线程模式详解 目录: 一、漫谈UML Java语言的线程 多线程的评量标准 二、 1、Single Threaded Execution ———— 能通过这座桥的,只有一个人 2、Immutable ———— 想破坏它也没办法 3、Guarded ...
三年级下册科学教案——第四单元5、磁力大小会变化吗.doc
EDA技术与VHDL第四版课件,潘松——第5章 VHDL并行语句
1.2 Linux的线程——轻量级进程 15 1.3 进程的创建——do_fork()函数详解 19 1.4 执行进程间切换 33 1.4.1 进程切换之前的工作 33 1.4.2 进程切换实务 —— switch_to宏 37 1.4.3 __switch_to函数 39 1.5 fork与...
信号与线性系统——第5章ppt