博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Mutex的使用
阅读量:4091 次
发布时间:2019-05-25

本文共 2273 字,大约阅读时间需要 7 分钟。

什么是Mutex

“mutex”是术语“互相排斥(mutually exclusive)”的简写形式,也就是互斥量。互斥量跟临界区中提到的Monitor很相似,只有拥有互斥对象的线程才具有访问资源的权限,由于互斥对象只有一个,因此就决定了任何情况下此共享资源都不会同时被多个线程所访问。当前占据资源的线程在任务处理完后应将拥有的互斥对象交出,以便其他线程在获得后得以访问资源。

Mutex的用途

  Mutex并不适合于有相互消息通知的同步;另一方面而我们也多次提到局部Mutex应该被Monitor/lock所取代;而跨应用程序的、相互消息通知的同步由将在后面讲到的EventWaiteHandle/AutoResetEvent/ManualResetEvent承担更合适。所以,Mutex在.net中应用的场景似乎不多。不过,Mutex有个最常见的用途:用于控制一个应用程序只能有一个实例运行。

using System;using System.Threading;class MutexSample{    private static Mutex mutex = null;  //设为Static成员,是为了在整个程序生命周期内持有Mutex    static void Main()    {        bool firstInstance;               mutex = new Mutex(true, @"Global\MutexSampleApp", out firstInstance);        try        {            if (!firstInstance)            {                Console.WriteLine ("已有实例运行,输入回车退出……");                Console.ReadLine();                return;            }            else            {                Console.WriteLine ("我们是第一个实例!");                for (int i=60; i > 0; --i)                {                    Console.WriteLine (i);                    Thread.Sleep(1000);                }            }        }        finally        {            //只有第一个实例获得控制权,因此只有在这种情况下才需要ReleaseMutex,否则会引发异常。            if (firstInstance)            {                mutex.ReleaseMutex();            }            mutex.Close();            mutex = null;        }    }}

  这是一个控制台程序,你可以在编译后尝试一次运行多个程序,结果当然总是只有一个程序在倒数计时。你可能会在互联网上找到其它实现应用程序单例的方法,比如利用 Process 查找进程名、利用Win32 API findwindow 查找窗体的方式等等,不过这些方法都不能保证绝对的单例。因为多进程和多线程是一样的,由于CPU时间片随机分配的原因,可能出现多个进程同时检查到没有其它实例运行的状况。这点在CPU比较繁忙的情况下容易出现,现实的例子比如傲游浏览器。即便你设置了只允许一个实例运行,当系统比较忙的时候,只要你尝试多次打开浏览器,那就有可能“幸运”的打开若干独立的浏览器窗口。

  别忘了,要实现应用程序的单例,需要在在整个应用程序运行过程中都保持Mutex,而不只是在程序初始阶段。所以,例子中Mutex的建立和销毁代码包裹了整个Main()函数。

使用Mutex需要注意的两个细节

  1. 可能你已经注意到了,例子中在给Mutex命名的字符串里给出了一个“Global\”的前缀。这是因为在运行终端服务(或者远程桌面)的服务器上,已命名的全局 mutex 有两种可见性。如果名称以前缀“Global\”开头,则 mutex 在所有终端服务器会话中均为可见。如果名称以前缀“Local\”开头,则 mutex 仅在创建它的终端服务器会话中可见,在这种情况下,服务器上各个其他终端服务器会话中都可以拥有一个名称相同的独立 mutex。如果创建已命名 mutex 时不指定前缀,则它将采用前缀“Local\”。在终端服务器会话中,只是名称前缀不同的两个 mutex 是独立的 mutex,这两个 mutex 对于终端服务器会话中的所有进程均为可见。即:前缀名称“Global\”和“Local\”仅用来说明 mutex 名称相对于终端服务器会话(而并非相对于进程)的范围。最后需要注意“Global\”和“Local\”是大小写敏感的。
  2. 既然父类实现了IDisposalble接口,那么说明这个类一定需要你手工释放那些非托管的资源。所以必须使用try/finally,亦或我讨厌的using,调用方法来释放Mutex所占用的所有资源!

参考

转载地址:http://stiii.baihongyu.com/

你可能感兴趣的文章
Springboot下使用Elasticsearch教程
查看>>
Springboot之Kafka
查看>>
Mac采用VMWare Fusion虚拟机安装Ubuntu16.04
查看>>
使用Ant Design of Vue前端框架编写项目过程中遇到的问题汇总
查看>>
vue语法 `${ }` (模版字符串)
查看>>
Vue中使用axios请求后端接口
查看>>
Vue实例的生命周期
查看>>
Vue中不同组件之间传值方法
查看>>
Vuex介绍及使用
查看>>
Vue知识:watch、computed和methods之间的对比
查看>>
nrm安装及使用
查看>>
Mybatis的一对多
查看>>
Vue学习:$event使用
查看>>
Vue学习:输入框点击回车触发事件
查看>>
递归练习一:输入一个字符串,打印出该字符串中字符的所有排列
查看>>
Vue Router的学习与使用
查看>>
Vue的插槽slot的使用
查看>>
let和var的区别
查看>>
Vue项目导入外部资源的方式
查看>>
js中遍历map对象键值的方法
查看>>