http://www.cnblogs.com/tianzhiliang/archive/2010/08/31/1813635.html
http://hi.baidu.com/bloodcrystal/blog/item/00ebd7f9da5aadd2b58f317c.html
信号量 Semaphore
类似互斥锁,但它可以允许多个线程同时访问一个共享资源
通过使用一个计数器来控制对共享资源的访问,如果计数器大于0,就允许访问,如果等于0,就拒绝访问。计数器累计的是“许可证”的数目,为了访问某个资源。线程必须从信号量获取一个许可证。
通常在使用信号量时,希望访问共享资源的线程将尝试获取一个许可证,如果信号量的计数器大于0,线程将获取一个许可证并将信号量的计数器减1,否则先线程将阻塞,直到获取一个许可证;当线程不再需要共享资源时,将释放锁拥有的许可证,并将许可证的数量加1,如果有其他的线程正在等待许可证,那么该线程将立刻获取许可证。
另外,允许同时访问的资源的进程数量是在创建信号量时指定的,如果创建一个允许进程访问的信号量数目为1,则该信号量就和互斥锁的用法一样。
Public Semaphore(int initialCount,int maximumCount)
initialCount指信号量许可证的初始值,maximumCount为最大值
获取许可证使用WaitOne()
不需要时释放使用 public int Release();或者public int Release(int releaseCount);
Semaphore与Mutex更像是兄弟,仍然与EventWaitHandle一脉不太亲近:
Semaphore从机制上来说跟Mutex一样属于“锁”而不是“通知”,因此跟Mutex一样几乎没有“通知”的能力。
举个不恰当但是很形象的例子,Semaphore就是一个可以多次进入的“Mutex”。Mutex永远只允许一个线程拥有它,而Semaphore可以允许多个线程请求,因此Semaphore被用于管理一次可以允许多个线程进入并发访问资源的情况。之所以说“不恰当”,是因为一旦允许多个线程访问资源,那么这时候的资源一定不是互斥资源,相应的代码段也不再是“临界区”。你千万不要以为我们在上一篇中提到的“糖罐”里有多颗糖就叫做“资源池”(都说过了嘛一个糖罐一定是需要互斥访问的),除非你有多个糖罐而不是多颗糖。
因为Semaphore与Mutex在请求数量上的不同,因此他们的线程相关性是不同的。这一点,Semaphore到跟EventWaitHandle一样,它是线程无关的。也就是说对Semaphore地释放者可以不定是Semaphore的拥有者。比如说我可以是消费者线程总使用WaitOne()请求线程池中的资源从来不需要释放,而生产者总是Release线程池中的资源而从来不请求。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace MyTTCon
{
class mythread
{
public Thread thrd;
//创建一个可授权2个许可证的信号量,且初始值为2
static Semaphore sem = new Semaphore(2, 2);
public mythread(string name)
{
thrd = new Thread(this.run);
thrd.Name = name;
thrd.Start();
}
void run()
{
Console.WriteLine(thrd.Name + "正在等待一个许可证……");
//申请一个许可证
sem.WaitOne();
Console.WriteLine(thrd.Name + "申请到许可证……");
for (int i = 0; i < 4; i++)
{
Console.WriteLine(thrd.Name + ": " + i);
Thread.Sleep(10000);
}
Console.WriteLine(thrd.Name + " 释放许可证……");
//释放
sem.Release();
}
}
class mysemaphore
{
public static void Main()
{
mythread mythrd1 = new mythread("Thrd #1");
mythread mythrd2 = new mythread("Thrd #2");
mythread mythrd3 = new mythread("Thrd #3");
mythread mythrd4 = new mythread("Thrd #4");
mythrd1.thrd.Join();
mythrd2.thrd.Join();
mythrd3.thrd.Join();
mythrd4.thrd.Join();
}
}
}