WaitHandle——使用Mutex

替代object加锁方式

使用System.object对象作为线程同步的工具,建立了一个基本的锁机制,确保资源只能同时被一个线程所访问。

但是这个对象不作任何其他用途,知识用于锁机制。

如果有一个类型可以专注于为线程同步的锁机制和信号量机制提供服务,那么上面的代码就可以简化。

.net中提供了更强大的system.threading.waithandle及其子类型,可以实现类似的效果。

首先来看Mutex是如何取代object的:

//System.Threading.Mutex 用于锁机制,同一时刻只能有一个线程拥有它,只有等到该线程释放,其他线程才能持有它。
//因此,使用mutex可以完成和lock语句相同的功能。
//对于mutex来说,waitone方法为获取互斥体
        //(等待其他线程发出释放互斥体信号,如果没有任何其他线程占有互斥体,则调用waitone的线程获取到互斥体)

//releaseMutex方法则用于释放互斥体

namespace 使用Mutex
{
    class Program
    {
        private string called = "";
        private System.Threading.Mutex mtx = new System.Threading.Mutex();//使用互斥体

        static void Main(string[] args)
        {
            Program p = new Program();

            Thread.CurrentThread.Name = "main ";
            Thread worker = new Thread(p.ThreadEntry);
            worker.Name = "worker ";
            worker.Start();
            p.ThreadEntry();

        }

        void ThreadEntry() {

            this.mtx.WaitOne();//等待该实例收到信号为止,类似enter
            string name = Thread.CurrentThread.Name;
            called += string.Format("{0}:{1}",name ,DateTime .Now .Millisecond);
            Console.WriteLine(called);
            this.mtx.ReleaseMutex();  //释放互斥体:类是exit

        }
    }
}

Mutex带有参数的构造函数

Mutex的构造函数接受一个bool类型的参数,指示创建Mutex的线程是否立即持有它;

相当于在mutex对象上调用waitone,其默认为false;

示例:

namespace Mutex有参数的构造函数
{
    class Program
    {

        public System.Threading.Mutex mtx = new System.Threading.Mutex(true);  //抢占:当前互斥体由主线程所有
        private string called = "";

        static void Main(string[] args)
        {
            Thread.CurrentThread.Name = "main ";
            Program p = new Program();
            Thread worker = new Thread(p.ThreadEntry);
            worker.Name = "worker";
            worker.Start();
            Thread.Sleep(100);  //让worker线程先执行:目的是为了让worker线程先执行;
            p.ThreadEntry();

            #region 防止主线程一直占有资源

                //Thread.Sleep(100);
                //p.MainJob();

            #endregion
        }

        void ThreadEntry() {

            this.mtx.WaitOne();//worker线程在进入此方法后,会一直阻塞在这里;因为当前互斥体由主线程所有。
            string name = Thread.CurrentThread.Name;
            called += string.Format("{0} {1}",name ,DateTime .Now.Millisecond);
            Console.WriteLine(called);
            this.mtx.ReleaseMutex();

        }

        #region 防止主线程一直占有资源

           //void MainJob()
           // {
           //     //在此线程中,至调用了ReleaseMutex方法,;
           //    //尽管对主线程使用了sleep方法,但是由于主线程持有互斥体,worker线程仍然会等待主线程先执行万mainjob方法才会继续执行

           //     string name = Thread.CurrentThread.Name;
           //     called += string.Format("{0} {1}", name, DateTime.Now.Millisecond);
           //     Console.WriteLine(called);
           //     this.mtx.ReleaseMutex();

           // } 

        #endregion

    }
}

Mutex创建Singleton应用程序

Mutex不仅提供跨线程的服务,还提供跨进程的服务。当在构造函数中为Mutex指定名称时,则会创建一个命名了的Mutex。

其他线程创建mutex时,如果指定的名称相同,则返回同一个互斥体,不论该线程位于哪个进程或者应用程序域中。

使用命名互斥体的一个例子是创建singleton应用程序,即只能打开一个实例的应用程序。

namespace Mutex创建singleton应用程序
{
    class Program
    {
        static void Main(string[] args)
        {
            string asm = Assembly.GetExecutingAssembly().GetName().Name;   //通过反射取值,获取到程序集的名称
            Mutex mtx = new Mutex(false ,asm);  //创建带有名称的互斥体

            if (!mtx.WaitOne (TimeSpan.FromMilliseconds (100)))   //该实例收到信号
            {
                Console .WriteLine ("{0} already running ",asm);  //提示该实例已经在运行了
                return ;  //直接return

            }

            //主线程第一次进入
            MainEntry(args);
            mtx.ReleaseMutex();//释放互斥体

        }

        static void MainEntry(string[] args) {

            Console.WriteLine("running~~~~~~~~~~~");
            Console.ReadLine();

        }
    }
}

时间: 2024-10-12 03:29:22

WaitHandle——使用Mutex的相关文章

C#多线程:深入了解线程同步lock,Monitor,Mutex,同步事件和等待句柄(中)

本篇继续介绍WaitHandler类及其子类 Mutex,ManualResetEvent,AutoResetEvent的用法..NET中线程同步的方式多的让人看了眼花缭乱,究竟该怎么去理解呢?其实,我们抛开.NET环境看线程同步,无非是执行两种操作:一是互斥/加锁,目的是保证临界区代码操作的"原子性":另一种是信号灯操作,目的是保证多个线程按照一定顺序执行,如生产者线程要先于消费者线程执行..NET中线程同步的类无非是对这两种方式的封装,目的归根结底都可以归结为实现互斥/ 加锁或者是

C# 多线程(lock,Monitor,Mutex,同步事件和等待句柄)

本文来自:http://www.cnblogs.com/SkySoot/archive/2012/04/02/2430295.html 本篇从 Monitor,Mutex,ManualResetEvent,AutoResetEvent,WaitHandler 的类关系图开始,希望通过本篇的介绍能对常见的线程同步方法有一个整体的认识,而对每种方式的使用细节,适用场合不会过多解释. 让我们来看看这几个类的关系图: 1. lock 关键字     lock 是 C# 关键词,它将语句块标记为临界区,确

.NET 同步与异步 之 EventWaitHandle(Event通知) (十三)

本随笔续接:.NET 同步与异步 之 Mutex (十二) 在前一篇我们已经提到过Mutex和本篇的主角们直接或间接继承自 WaitHandle: Mutex类,这个我们在上一篇已经讲过. EventWaitHandle 类及其派生类AutoResetEvent 和 ManualResetEvent,这是本篇的主角. Semaphore 类,即信号量,我们下一篇再讲(忽然觉得没有必要介绍了). WaitHandle提供了若干用于同步的方法.上一篇关于Mutex的blog中已经讲到一个WaitOn

.Net线程问题解答

基础篇 怎样创建一个线程 受托管的线程与 Windows线程 前台线程与后台线程 名为BeginXXX和EndXXX的方法是做什么用的 异步和多线程有什么关联 WinForm多线程编程篇 我的多线程WinForm程序老是抛出InvalidOperationException ,怎么解决? Invoke,BeginInvoke干什么用的,内部是怎么实现的 每个线程都有消息队列吗? 为什么Winform不允许跨线程修改UI线程控件的值 有没有什么办法可以简化WinForm多线程的开发 线程池 线程池

WinForm多线程学习文档

基础篇 怎样创建一个线程 受托管的线程与 Windows线程 前台线程与后台线程 名为BeginXXX和EndXXX的方法是做什么用的 异步和多线程有什么关联 WinForm多线程编程篇 我的多线程WinForm程序老是抛出InvalidOperationException ,怎么解决? Invoke,BeginInvoke干什么用的,内部是怎么实现的 每个线程都有消息队列吗? 为什么Winform不允许跨线程修改UI线程控件的值 有没有什么办法可以简化WinForm多线程的开发 线程池 线程池

C#线程同步技术(一) lock 语句

开篇语: 上班以后,烦恼少了,至少是没有什么好烦的了,只要负责好自己的工作就可以了,因此也有更多的时间去探索自己喜欢的程序.买回来的书已经看了一半,DEMO也敲了不少,昨晚终于在这里开BLOG,记录一些读书笔记.以我自己的经验来看,写笔记.测试.体会是加深理解的利器,往往起到事半功倍的效果.这几天在看任务.线程和同步的部分,就用这个练练笔,记录一些学习的心得. 一.一个小测试 本文讨论的是线程同步的技术,假定你已经理解相关概念.如果未接触过,或者理解得不多,且看下面的小例子: public cl

CLR 线程同步

CLR 基元线程同步构造 <CLR via C#>到了最后一部分,这一章重点在于线程同步,多个线程同时访问共享数据时,线程同步能防止数据虽坏.之所以要强调同时,是因为线程同步问题其实就是计时问题.为构建可伸缩的.响应灵敏的应用程序,关键在于不要阻塞你拥有的线程,使它们能用于(和重用于)执行其他任务. 不需要线程同步是最理想的情况,因为线程同步存在许多问题: 1 第一个问题是,它比较繁琐,很容易出错. 2 第二个问题是,它们会损坏性能.获取和释放锁是需要时间的,因为要调用一些额外的方法,而且不同

WaitHandle——使用ManualResetEvent

信号量机制 使用ManualResetEvent和AutoResetEvent都继承自EventWaitHandle(继承自waitHandle).EventWaitHandle对象有两个状态:收到信号(signaled)和未收到信号(nonsignaled):EventWaitHandle中的set和reset方法分别用于将eventwaitHandle对象的状态设为收到信号和未收到信号. 当EventWaitHandle未收到信号时,任何线程调用基类的wait方法都会被阻塞,知道eventh

WaitHandle——使用Semaphore

semaphore也继承自waithandle,它用于锁机制,与Mutex不同的是,它允许指定数量的线程同时访问资源,在线程超过数量以后,则进行排队等待,直到之前的线程退出. Semaphore很适合应用于web服务器这样的高并发场景,可以限制对资源访问的线程数. Monitor与monitor都有一个锁持有者,而semaphore则不需要,因此通常将sempahore声明为静态的. 来看下面的示例: namespace 使用Semaphore { class Program { //第一个参数