上一篇咱们介绍了互斥体,这一篇介绍信号量。。。。。。。。。。。。函数
1、什么是信号量?spa
信号量对象对线程的同步方式与前面几种方法不一样,信号容许多个线程同时使用共享资源,这与操做系统中的PV操做相同。它指出了同时访问共享资源的线程最大数目。它容许多个线程在同一时刻访问同一资源,可是须要限制在同一时刻访问此资源的最大线程数目。在建立信号量时即要同时指出容许的最大资源计数和当前可用资源计数。通常是将当前可用资源计数设置为最大资源计数,每增长一个线程对共享资源的访问,当前可用资源计数就会减1,只要当前可用资源计数是大于0的,就能够发出信号量信号。可是当前可用计数减少到0时则说明当前占用资源的线程数已经达到了所容许的最大数目,不能在容许其余线程的进入,此时的信号量信号将没法发出。线程在处理完共享资源后,应在离开的同时经过ReleaseSemaphore()函数将当前可用资源计数加1。在任什么时候候当前可用资源计数决不可能大于最大资源计数。操作系统
信号量有一个使用计数器,这个使用计数器,是信号量的最大资源计数和当前资源计数的差值。线程
2、信号量的使用原理? code
a、若是当前资源计数大于0,那么信号量处于触发状态。orm
b、若是当前资源计数等于0,那么信号量处于未触发状态。对象
c、系统绝对不会让当前资源计数变为负数。blog
d、当前资源计数绝对不会大于最大最大资源计数进程
3、示例 事件
一、线程间的sempahore同步
若是出现 WaitOne 就一个要有对应的Release 即获取信号量后,必定要释放。
如:6个进程须要同时使用打印机,而电脑上只有四台打印机,则打印机是被保护的资源,信号量为4。则须要用semaphore来同步。
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace SemaphoreClass { class Program { static void Main(string[] args) { int sourceCount = 4;//打印机数量 int threadCount = 6;//须要打印的线程数目 // maximumCount-initialCount 之间的差值为已经锁定的 semaphore的数量(即信号量使用计数器) 此实例中已经指定占用了0个信号量 //Semaphore的第三个参数为信号量的名称,若是设定了名称,则可用于进程间的同步,若是没有设置名称则只能用于进程内的线程同步 Semaphore sempaphore = new Semaphore(sourceCount, sourceCount, "sempaphore"); Thread[] threads = new Thread[threadCount]; for (int i = 0; i < threadCount; i++) { threads[i] = new Thread(ThreadMain); threads[i].Start(sempaphore); } for (int i = 0; i < threadCount; i++) { threads[i].Join(); } Console.WriteLine("All threads finished!"); Console.ReadKey(); } /// <summary> /// 线程执行的方法 /// </summary> /// <param name="o"></param> static void ThreadMain(object o) { Semaphore semaphore = o as Semaphore; Trace.Assert(semaphore != null, "o must be a semphore type"); bool isCompleted = false; while (!isCompleted) { //锁定信号量,若是锁定计数已经达到最高计数限制,则等待600毫秒。若是在600毫秒后未能得到锁定,则返回false。 if (semaphore.WaitOne(600, false)) { try { Console.WriteLine("Thread {0} locks the semaphore ", Thread.CurrentThread.ManagedThreadId); Thread.Sleep(2000); } finally { //解除资源的锁定。参数为退出信号量的次数。占用一个信号量故退出一个。 semaphore.Release(1); Console.WriteLine("Thread {0} release the semaphore", Thread.CurrentThread.ManagedThreadId); isCompleted = true; } } else { Console.WriteLine("Timeot for thread {0}; wait again", Thread.CurrentThread.ManagedThreadId); } } } } }
二、进程间的sempahore同步
下面的例子将使用信号量来同步进程,一个应用程序能够有二个实例运行(若是只容许有一个实例来运行,最优之选是mutex,其次才是信号量)。虽然这个例子不太实用,但彻底能够说明semaphore的特性。
注意:生成解决方案后运行三次生成EXE,就会看到结果。信号量的进程同步和信号量的应用程序的名称无关。只要使用了一样名称的信号量,他们以前就存在了一种协约。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace SemaphoreProcess { class Program { static void Main(string[] args) { //定义可同步运行的可用实例数 int CreateNew = 2; //定义可同步运行的最大实例数 int MaxCreateNew = 5; // maximumCount-initialCount 之间的差值为已经锁定的 semaphore的数量 此实例中已经指定占用了3个信号量 计算方式为(MaxCreateNew-CreateNew) //Semaphore的第三个参数为信号量的名称,若是设定了名称,则可用于进程间的同步,若是没有设置名称则只能用于进程内的线程同步 System.Threading.Semaphore sempaphore = new System.Threading.Semaphore(CreateNew, MaxCreateNew, "sempaphoreProcess"); if (sempaphore.WaitOne(100, false)) { Console.WriteLine("系统正在运行……"); Console.ReadKey(); } else { MessageBox.Show("当前已经有 " + CreateNew + " 个实例在运行,系统将退出!", "您好", MessageBoxButtons.OK, MessageBoxIcon.Information); } } } }
下一篇介绍事件。。。。。。。。。。。。