`
wangminshe89
  • 浏览: 703600 次
文章分类
社区版块
存档分类
最新评论

5天不再惧怕多线程——第四天 信号量

 
阅读更多

今天整理“信号量”的相关知识,其实想想也蛮有趣的,锁,互斥,信号量都可以实现线程同步,在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,后续的线程只能苦苦的等待。

0
0
分享到:
评论

相关推荐

    qt5多线程,信号量,互斥量,等待条件

    总的来说,QT5的多线程支持、信号量、互斥量和等待条件提供了强大的工具,可以帮助开发者编写出高效、安全的并发代码。在实际的软件开发中,正确地使用这些同步原语对于解决并发问题和优化性能至关重要。

    多线程编程——线程的同步

    在“多线程编程之四——线程的同步”这个文件中,可能包含了上述各种同步机制的具体实现示例和详细说明,这对于初学者来说是一份非常宝贵的参考资料。通过学习和理解这些例子,开发者可以更好地掌握如何在实际项目中...

    12.2 Qt5多线程:使用信号量实现生产者和消费者

    在编程领域,多线程是实现并发执行任务的重要方式,特别是在GUI应用如Qt5中,多线程可以提高程序的响应速度和效率。本主题主要关注如何使用Qt5的QSemaphore类来解决经典的生产者-消费者问题。QSemaphore是一种同步...

    C#信号量,用于多线程

    ### C#中的信号量Semaphore与多线程管理 在探讨C#中的`Semaphore`类之前,我们先简单回顾一下多线程的基本概念。在计算机科学领域,多线程是指一个程序内部可以同时运行多个线程(即执行路径),每个线程都可以独立...

    多线程编程之三——线程间通讯

    标题与描述均提到了“多线程编程之三——线程间通讯”,这明确指出了文章的核心主题:在多线程编程环境下,不同线程之间的通信机制。在现代软件开发中,尤其是涉及到高性能计算、并发处理以及分布式系统设计时,线程...

    哈工大软件学院操作系统实验4——信号量的实现和应用

    5. **哲学家就餐问题**:这是一个经典的多进程同步问题,可能作为实验的一个示例,通过信号量解决五个哲学家同时使用四根筷子吃饭的问题。 6. **读者-写者问题**:另一经典问题,允许多个读者同时读取数据,但当有写...

    Qt 多线程连接数据库——数据库连接池

    * 支持多线程,保证获取到的连接一定是没有被其他线程正在使用 * 按需创建连接,可以创建多个连接,可以控制连接的数量 * 连接被复用,不是每次都重新创建一个新的连接(连接的创建是一个很消耗资源的过程) * ...

    QT6之多线程控制-互斥量和信号量

    在多线程编程中,互斥量(Mutex)和信号量(Semaphore)是两种重要的同步机制,它们用于管理和保护共享资源,防止数据竞争和死锁等问题。本文将深入探讨在QT6中如何使用互斥量和信号量进行多线程控制。 首先,让...

    pb9多线程控件,能够真实实现多线程

    4. 共享机制与多线程的区别:PB自带的共享机制可能不提供完全并发执行,而多线程可以真正实现并行处理。 5. 示例代码的重要性:提供的示例可以帮助开发者理解如何在PB9中正确地使用多线程控件。 6. 移植问题:从PB...

    线程基本编程——线程函数大全.doc

    线程基本编程——线程函数大全 线程编程是操作系统中的一种重要概念,它允许在同一个进程中执行多个线程,从而提高系统的并发性和效率。线程编程需要使用一些特殊的函数来创建、管理和控制线程的生命周期。在本文中...

    多线程框架通用多线程源码.zip

    此外,"大漠多线程"是一个常见的易语言多线程库,它提供了丰富的多线程操作接口,包括线程同步、互斥量、信号量等高级功能。结合"511遇见"这个标签,可能意味着这个框架是在易语言社区交流中广泛讨论和分享的成果,...

    delphi7 多线程测试(40个线程)

    5. **同步开销**:为了确保线程安全,程序可能需要使用各种同步原语(如锁、信号量、事件等)。过多的同步操作会降低执行速度,尤其是当大部分时间花在等待其他线程释放资源上时。 6. **设计问题**:如果每个线程都...

    QT 下 信号量使用

    在QT框架中,信号量(Semaphore)是一种非常重要的同步机制,它源于进程间通信(IPC)的概念,并在多线程编程中广泛使用。信号量允许我们控制对共享资源的访问,确保同一时间只有一个线程或者有限数量的线程能够访问...

    java多线程处理数据(csdn)————程序.pdf

    Java多线程处理数据是一种常见的优化策略,尤其在面临大量数据查询时,通过并发执行任务可以显著提升程序的运行效率。以下将详细解释这个程序中的关键知识点: 1. **Callable接口**:`ThredQuery`类实现了`Callable...

    MATLAB程序——癫痫病人的脑电信号提取

    在本项目中,“MATLAB程序——癫痫病人的脑电信号提取”是针对神经科学领域的一个具体应用,主要涉及MATLAB编程和Bash脚本技术,用于分析来自癫痫患者的神经数据。这个项目很可能是一个研究或临床诊断工具,旨在通过...

    QT5多线程TCP服务器和客户端demo

    QT5是一个功能强大的跨平台应用程序开发框架,特别...总结,QT5多线程TCP服务器和客户端的实现涉及到了多线程编程、网络编程以及QT的信号槽机制。理解并熟练运用这些知识点,能够帮助开发者构建健壮、高效的网络应用。

    QT多线程实战源代码(QThread)

    4. **线程安全**:讨论了在多线程环境下如何保证数据的一致性和完整性,可能包括互斥锁(QMutex)、信号量(QSemaphore)等同步原语的使用。 5. **异常处理**:在多线程环境中,异常处理是必不可少的,确保错误发生...

    java多线程的使用和介绍

    - **Win32线程模型**:在Windows操作系统中,线程模型支持两种类型的线程——单线程模型(STA)和多线程模型(MTA)。STA线程通常用于UI相关的任务,而MTA线程则用于一般的计算任务。 - **Java中的线程模型**:Java...

    qt v4l2多线程视频采集

    【标题】:“Qt V4L2多线程视频采集”是指使用Qt库结合Video for Linux 2 (V4L2)接口,在多个线程中进行视频捕获的技术。V4L2是Linux内核提供的一种标准接口,用于与各种视频设备(如摄像头)交互。而Qt是一个跨平台...

    C#.NET多线程实例6个(包括多线程基本使用,多线程互斥等全部多线程使用实例)(十分经典)

    `AutoResetEvent`和`ManualResetEvent`是两种常用的信号量,用于在多个线程之间传递信号。 6. **线程优先级**: C#允许设置线程的优先级,但应谨慎使用,因为优先级高的线程并不保证总是先执行,且可能导致优先级...

Global site tag (gtag.js) - Google Analytics