public class Program { static Semaphore sema = new Semaphore(5, 5); const int cycleNum = 9; static void Main(string[] args) { for(int i = 0; i < cycleNum; i++) { Thread td = new Thread(new ParameterizedThreadStart(testFun)); td.Name = string.Format("编号{0}",i.ToString()); td.Start(td.Name); } Console.ReadKey(); } public static void testFun(object obj) { sema.WaitOne(); Console.WriteLine(obj.ToString() + "进洗手间:" + DateTime.Now.ToString()); Thread.Sleep(2000); Console.WriteLine(obj.ToString() + "出洗手间:" + DateTime.Now.ToString()); sema.Release(); } }
这里我要说明一点,信号量控制的只是线程同步的量,而不管顺序,这个例子来说线程控制的就是线程同步量为5,也就是同时并发的线程数量为5个,至于是哪个先哪个后不是由这里的信号量决定的。
当然这个例子中因没有做什么复杂的操作,一般情况进入线程的时间和每个线程要的时间不会有太大差别,所以执行的顺序还是很规律的(为了说明这个问题我也是运行了多次才让结果稍有不同,这里编号2抢在了编号1前面就是这个道理),如果线程中有很复杂的操作每个线程在运行中所用的时间有比较大的差别,或者循环开始有复杂操作那么很可能就不是编号0先进入洗手间了,且不一定是先进入的就会先出来。
接下来再简单介绍一下Semaphore的WaitOne()和Release()的重载方法
public int Release(int releaseCount);releaseCount指的是释放的信号量数量,如果没有参数默认为1,Release()就相当于Release(1)
这里要说明一点,当Release()或者Release(int releaseCount)执行时导致信号量计数大于最大数量时会抛出SemaphoreFullException异常。下面这种情况就会异常:
Semaphore sem = new Semaphore(4,5); sem.Release(2);//这里是释放2个信号量加上之前的4个,超出5个了public virtual bool WaitOne(TimeSpan timeout); public virtual bool WaitOne(int millisecondsTimeout);第一个重载参数timeout:指定时间间隔,若在这段时间内没有接收到信号则跳过等待继续执行
第二个重载参数millisecondsTimeout:指定时间间隔整数毫秒,若在这段时间内没有接收到信号则跳过等待继续执行
WaitOne()还有两个重载方法不是很常用这里就不介绍了。上面的重载方法这里也不再进了案例说明了,有兴趣的朋友可以自己尝试一下