Semaphore(信号量)
Semaphore
msdn介绍:
限制可同时访问某一资源或资源池的线程数。
命名空间: System.Threading
程序集: System(在 System.dll 中)
通俗理解:
1:宾馆开房 房间只能住3个人,现在来了5个人。
2:开门进去3个人 这个时候还有2个人只能在外面等待了。
3:如果出来一个人 剩下的2个进去其中1个。 同理房间还是3个人
后面如果继续来人。 如此往复
核心 总数3个人 。对应msdn 就是允许3个人同时访问 某一资源或资源池的线程数。
构造函数为initialCount和maximumCount,表示默认设置的信号量个数和最大信号量个数,
其实说到底,里面是采用计数器来来分配信号量,
当你WaitOne的时候,信号量自减,
当Release的时候,信号量自增,
然而当信号量为0的时候,后续的线程就不能拿到WaitOne了,所以必须等待先前的线程通过Release来释放。
代码:
namespace ConsoleApplication2 { class Program { static Semaphore sh = new Semaphore(2, 10); static void Main(string[] args) { Thread t1 = new Thread(Run); t1.Name = "t1"; Thread t2 = new Thread(Run); t2.Name = "t2"; Thread t3 = new Thread(Run); t3.Name = "t3"; Thread.Sleep(100); t1.Start(); t2.Start(); Thread.Sleep(100); t3.Start(); Console.Read(); } static void Run() { sh.WaitOne(); Console.WriteLine("大家好,我是{0}", Thread.CurrentThread.Name); } } }
图:
t3 永远都出不来了 原因
static Semaphore sh = new Semaphore(2, 10);
sem.WaitOne(); 就是吧2-- 这里执行2次就变0了
我计数器是2 就是类似上面的房间只能3个人。
10是最大容量 现在进去了2个自然t3出不来了。
这个时候我们手动干预一下,
我们知道调用Release方法相当于自增一个信号量也可以加到maximunCount个信号量 即这里的10
代码:
namespace ConsoleApplication2 { class Program { static Semaphore sh = new Semaphore(2, 10); static void Main(string[] args) { Thread t1 = new Thread(Run); t1.Name = "t1"; Thread t2 = new Thread(Run); t2.Name = "t2"; Thread t3 = new Thread(Run); t3.Name = "t3"; Thread.Sleep(100); t1.Start(); t2.Start(); t3.Start(); Thread.Sleep(10000); sh.Release(10); Console.Read(); } static void Run() { sh.WaitOne(); if (Thread.CurrentThread.Name == "t3") { Console.WriteLine("我终于出来了 我是被sh.Release(10)解放的 我的名字是{0}", Thread.CurrentThread.Name); } else { Console.WriteLine("大家好,我是{0}", Thread.CurrentThread.Name); } } } }
Semaphore升级进程交互。
在VS对象浏览器中发现Semaphore是继承字WaitHandle,而WaitHandle封装了win32的一些同步机制,所以当我们给Semaphore命名的时候
就会在系统中可见
namespace System.Threading { // 摘要: // 限制可同时访问某一资源或资源池的线程数。 [ComVisible(false)] public sealed class Semaphore : WaitHandle { ......... } }
把下面的代码copy一份,运行两个程序。
namespace ConsoleApplication2 { class Program { static Semaphore sh = new Semaphore(3, 10,"tsp"); static void Main(string[] args) { Thread t1 = new Thread(Run); t1.Name = "t1"; Thread t2 = new Thread(Run); t2.Name = "t2"; t1.Start(); Thread.Sleep(100); t2.Start(); Console.Read(); } static void Run() { sh.WaitOne(); Console.WriteLine("当前时间:{0} 大家好,我是{1}", DateTime.Now, Thread.CurrentThread.Name); } } }
t2也出不来了。