WaitHandle学习笔记

Posted CodeLife

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WaitHandle学习笔记相关的知识,希望对你有一定的参考价值。

信号量与互斥体              

互斥体(Mutex)是操作系统中一种独占访问共享资源的机制。它像一把所锁,哪个线程获取到互斥体的控制权,则可以访问共享的资源,或者执行处于受保护的代码。而其他的线程如果也想获取控制权,则需要要阻塞等待,知道拥有控制权的线程释放控制权。

信号量(Semaphore)是操作系统中协调多个线程访问共享资源的机制。他内部维护一个非负整数计数器。0表示不能再接受更多的共享访问请求,大于零的数值X表示最多还能接受X个线程的共享访问请求。而非负整数的操作只能通过wait()或者signal()来进行原子操作。signal将计数器加1; wait()将计数器减1,如果当前值为0则阻塞知道有其他线程调用signal。通过这种机制来实现最多X个线程访问共享资源。这种机制通常可以用来解决生产者和消费者问题。(假如产品队列最多能装X个产品,生产者相当于wait操作,消费者相当于signal操作)

.NET 中的WaitHandle           

 在.Net Framework中有上图中三个子类。用来表示操作系统中的互斥体和信号量。

Mutex

Mutex是对操作系统中互斥体的包装,可以创建未命名的本地Mutex(只在当前进程有效),也可以创建命名的全局Mutex(操作系统有效,跨进程)。具体操作如下:

 

            var _mutex = new Mutex(false);
            new Task(() =>
            {
                _mutex.WaitOne();//获取mutex控制权
                Console.WriteLine("Got mutex signal. Thread Id:1");
                Thread.Sleep(1000);
                _mutex.ReleaseMutex();//释放mutex控制权
                Console.WriteLine("Release mutex signal, Thread Id:1");
            }).Start();

            new Task(() =>
            {
                _mutex.WaitOne();//获取mutex控制权,在thread 1释放之前,该调用会阻塞
                Console.WriteLine("Got mutex signal Thread id:2");
                Thread.Sleep(1000);
                _mutex.ReleaseMutex();
                Console.WriteLine("Release mutex signal, Thread Id:2");

            }).Start();

 

在操作Mutex时,系统会检查Thread Identity,只有获取Mutex控制权的线程才能释放控制权。

Semaphore

Semaphore是对操作系统中信号量的包装,同样也可以创建未命名的Semaphore(只在当前进程有效)和命名的全局Semaphore(操作系统有效,跨进程)具体操作如下:

但是在操作Semaphore时,和Mutex不一样,系统不会检查Thread Identity。任何线程都可以对Semaphore进行WaitOne()和Release()

 

            var _semaphore = new Semaphore(2, 2);//设置最大允许访问共享资源线程数为2

            new Task(() =>
            {
                for (int index = 0; index < 3; index++)
                {
                    _semaphore.WaitOne();//第三次调用该方法是会被阻塞,因为计数器为0.当其他线程调用Release后才能继续
                    Console.WriteLine("Got Semaphore Signal. Thread Id:" + Thread.CurrentThread.ManagedThreadId);
                }
            }).Start();

            new Task(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("Release Semaphore, Thread Id:" + Thread.CurrentThread.ManagedThreadId);
                _semaphore.Release();//计数器+1
            }).Start();

 

EventWaitHandle

这个类其实提供了和Mutex类似的线程之间同步,通知机制。它也能创建本地WaitHandle和全局WaitHandle。但是和Mutex又有区别:

  • 它内部其实维护了一个布尔类型变量来标示当前wait handle是否空闲:true表示空闲,可以被申请控制权; false则表示wait handle已经被线程持有控制权。(当调用WaitOne获取控制权时,如果内部标量为false,则阻塞知道其他线程将其Set为true.)而对该变量的操作只能通过Set()(将变量设为true),Reset()(将变量设为false)来进行原子操作。
  • EventWaitHandle并不提供独占操作,当内部变量为true时,所有线程的WaitOne操作都能获取到控制权,而不是只有一个能获取到(通过设置WaitHandle为AutoReset也可以实现)
  • 在操作EventWaitHandle时,系统也不会检查Thread Identity

具体操作如下:

            var _waitHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
       //这里指定AutoReset类型后,WaitOne调用获取到控制权后会同时将内部变量置为false,相当于调用Reset()
new Task(() => { _waitHandle.WaitOne(); Console.WriteLine("Got the signal, thread id:" + Thread.CurrentThread.ManagedThreadId); }).Start(); new Task(() => { _waitHandle.WaitOne(); Console.WriteLine("Got the signal, thread id:" + Thread.CurrentThread.ManagedThreadId); }).Start(); new Task(() => { Console.WriteLine("Set the signal, thread id:" + Thread.CurrentThread.ManagedThreadId); _waitHandle.Set(); }).Start();

 

以上是关于WaitHandle学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

WaitHandle.WaitAny 匹配 WaitForMultipleObjects 功能

[原创]java WEB学习笔记61:Struts2学习之路--通用标签 property,uri,param,set,push,if-else,itertor,sort,date,a标签等(代码片段

DOM探索之基础详解——学习笔记

System.Threading.WaitHandle.cs

学习笔记 链接

ReactJs学习笔记01