javaee论坛

普通会员

225648

帖子

345

回复

359

积分

楼主
发表于 2017-06-20 04:32:54 | 查看: 96 | 回复: 2
当多个任务或线程并行运行时,难以避免的对某些有限的资源进行并发的访问。可以考虑使用信号量来进行这方面的控制(System.Threading.Semaphore)是表示一个Windows内核的信号量对象。如果预计等待的时间较短,可以考虑使用SemaphoreSlim,它则带来的开销更小。

.NetFrameWork中的信号量通过跟踪进入和离开的任务或线程来协调对资源的访问。信号量需要知道资源的最大数量,当一个任务进入时,资源计数器会被减1,当计数器为0时,如果有任务访问资源,它会被阻塞,直到有任务离开为止。

使用超时和取消

信号量当然不可能永久的阻塞在那里。信号量也提供了超时处理机制。方法是在Wait函数中传入一个超时等待时间 - Wait(int TIMEOUT)。当Wait返回值为false时表明它超时了。如果传入了 -1,则表示无限期的等待。

跨进程或AppDomain的同步

如果需要有跨进程或AppDomain的同步时,可以考虑使用Semaphore。Semaphore是取得的Windows 内核的信号量,所以在整个系统中是有效的。
它主要的接口时 Release和WaitOne,使用的方式和SemaphoreSlim是一致的。


信号量Semaphore是另外一个CLR中的内核同步对象。在.net中,类Semaphore封装了这个对象。与标准的排他锁对象(Monitor,Mutex,SpinLock)不同的是,它不是一个排他的锁对象,它与SemaphoreSlim,ReaderWriteLock等一样允许多个有限的线程同时访问共享内存资源。

Semaphore就好像一个栅栏,有一定的容量,当里面的线程数量到达设置的最大值时候,就没有线程可以进去。然后,如果一个线程工作完成以后出来了,那下一个线程就可以进去了。Semaphore的WaitOne或Release等操作分别将自动地递减或者递增信号量的当前计数值。当线程试图对计数值已经为0的信号量执行WaitOne操作时,线程将阻塞直到计数值大于0。在构造Semaphore时,最少需要2个参数。信号量的初始容量和最大的容量。

Semaphore的WaitOne或者Release方法的调用大约会耗费1微秒的系统时间,而优化后的SemaphoreSlim则需要大致四分之一微秒。在计算中大量频繁使用它的时候SemaphoreSlim还是优势明显,加上SemaphoreSlim还丰富了不少接口,更加方便我们进行控制,所以在4.0以后的多线程开发中,推荐使用SemaphoreSlim。


Test.cs代码:

< class="ttyprint"> class Test { static SemaphoreSlim _semaphore = new SemaphoreSlim(4); static void AccessDatabase(string name, int seconds) { Console.WriteLine("{0} 等待访问数据库", name); _semaphore.Wait(); Console.WriteLine("{0} 被授予对数据库的访问权限", name); Thread.Sleep(TimeSpan.FromSeconds(seconds)); Console.WriteLine("{0} 完成了", name); _semaphore.Release(); Console.ReadKey(); } public static void RunTest() { for (int i = 1; i < 7; i++) { string threadName = "Thread" + i; var t = new Thread((() => AccessDatabase(threadName, 2))); t.Start(); } } }

运行结果如图:

这里写图片描述


普通会员

1

帖子

311

回复

317

积分
沙发
发表于 2023-08-23 13:20:47

百因必有果你的报应就是我

普通会员

0

帖子

311

回复

315

积分
板凳
发表于 2024-04-24 15:56:30

我喜欢

您需要登录后才可以回帖 登录 | 立即注册

触屏版| 电脑版

技术支持 历史网 V2.0 © 2016-2017