zoukankan      html  css  js  c++  java
  • 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();
  • 相关阅读:
    Java设计模式系列之策略模式
    设计模式系列之热身
    算术表达式系列之后缀表达式求值
    算术表达式系列之中缀表达式转后缀表达式
    Maven下使用Junit对Spring进行单元测试
    Windows命令行使用总结(持续更新)
    Eclipse中web项目部署至Tomcat步骤
    MyBatis保存完整日期的解决方法
    Redis(一)源码安装
    【集成学习】sklearn中xgboost模块中plot_importance函数(绘图--特征重要性)
  • 原文地址:https://www.cnblogs.com/Code-life/p/8030057.html
Copyright © 2011-2022 走看看