c#多线程同步之Semaphore
一提到Semaphore(信号量)的使用,还挺有意思的,它允许多个线程同时访问多个稀有资源,我立马想到银行的ATM机取钱的场景。看下面的代码:
1 static Semaphore sem = new Semaphore(2, 4); 2 3 public static void StartThread(string name) 4 { 5 var t = new Thread(run); 6 t.Name = name; 7 t.Start(); 8 } 9 static void run() 10 { 11 string name = Thread.CurrentThread.Name; 12 Console.WriteLine(name + "正在等待ATM小房子……"); 13 //申请一个许可证 14 sem.WaitOne(); 15 Console.WriteLine(name + "进入ATM小房子……"); 16 Console.WriteLine(name + "开始操作ATM"); 17 Thread.Sleep(1000); 18 Console.WriteLine(name + "操作ATM结束"); 19 Console.WriteLine(name + " 从ATM小房子出来了……"); 20 //释放 21 sem.Release(); 22 } 23 static void Main(string[] args) 24 { 25 for (int i = 0; i < 4; i++) 26 { 27 StartThread("#" + (i + 1)); 28 } 29 Console.Read(); 30 }
Semaphore构造函数,第一个参数表示当前可用资源数,第二个参数表示最大资源数。可用资源数不能超过最大资源数,否则c#运行时会抛出异常。当初始资源为0时,看看结果:
这个结果说明,4个ATM,当前都有人占用着,所以四个人处于等待状态。
当我们把初始资源数设为4,结果:
上图说明,四个人都没有等待,而是直接进入了ATM机的小房子。当资源足够用的时候,就不存在稀缺资源这么一说了。
当我们把初始资源数设为1时,再次看看结果:
当我们把资源数设置为1时,这时候不就和互斥体产生的效果一样了吗?这就好比众多的病人在一个诊室等着看病一样,医生只能一个一个地来。
总之,信号量内部维护了一个对稀有资源的计数器,当一个资源被用时(调用WaitOne方法,一直阻塞线程,直到有可用资源),这个计数器-1,当一个资源被释放(调用Release方法)时,这个计数器+1,如果计数器为0时,表示资源耗尽了,那么所有线程都处于等待状态。