好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

mutex互斥锁

mutex互斥锁

NET多线程探索-互斥锁,信号量,事件(小新和拆弹部队友情演出)

2012-03-22 17:14 by 海不是蓝, 835 visits,  收藏 ,  编辑

mutex互斥锁-不准确的时钟

概念性的东西: 
互斥锁是一个互斥的同步对象,一个时间只有一个线程可以获取它。 
前一篇文章中的时钟程序我们这里用Mutex互斥锁来实现。

 class   Program
 {
     static void  Main( string [] args)
    {
         Clock  C =  new   Clock ();
        C.RunClock(1);
         Console .Read();
    }
}
 public class   Clock
 {
     public   Mutex  Mtx =  new   Mutex ();

     //开始运行时钟,输入运行分钟
      public void  RunClock( Int32  Minute)
    {
         Thread  T1 =  new   Thread (( object  Minute1) =>
        {
             Int32  m =  Convert .ToInt32(Minute1) * 60 / 2;
             while  (m > 0)
            {
                DI( true );
                m--;
            }
        });
         Thread  T2 =  new   Thread (( object  Minute1) =>
        {
             Int32  m =  Convert .ToInt32(Minute1) * 60 / 2;
             while  (m > 0)
            {
                DA( true );
                m--;
            }
        });
        T1.Start( true );
        T2.Start( true );
    }

     public void  DI( bool  run)
    {
        Mtx.WaitOne();
         if  (!run)
        {
            Mtx.ReleaseMutex();
             return ;
        }
         else
         {
             Console .WriteLine( "嘀" );
             Thread .Sleep(1000);
            Mtx.ReleaseMutex();
        }
    }

     public void  DA( bool  run)
    {
        Mtx.WaitOne();
         if  (!run)
        {
            Mtx.ReleaseMutex();
             return ;
        }
         else
         {
             Console .WriteLine( "嗒" );
             Thread .Sleep(1000);
            Mtx.ReleaseMutex();
        }
    }
}

 
为什么会这样?貌似一切都是合理的!


这里我只发表下我的理解,还请个位园友自己认真分析下,毕竟我个人理解可能是错误的! 
如果您发现我理解错了,请在评论指出,我好及时学习更早! 

Monitor的时钟是使用了lock来锁定,lock最后也会被编译成为Monitor的Enter和Exit。 
重点是Monitor在Pulse(obj)的时候已经就确定了另外一个等待obj被释放的线程拥有了执行权! 
而Mutex在ReleaseMutex在释放锁定之后,当前线程和其他等待线程都执行WaitOne,导致了线程执行权的争夺! 
随着程序的运行,线程之间的争夺激烈。

mutex互斥锁-杯具的拆弹手



下面用互斥锁实现个例子,一个炸弹,同时只能一个人拆弹,如果超过1个人就爆炸。

 class   Program
 {
     static void  Main( string [] args)
    {
         炸弹  b =  new   炸弹 ();
        b.拆弹();
        b.拆弹();
         Console .Read();
    }
}
 public class   炸弹
 {
     private   Int32  热度 = 0;
     public   Mutex  m =  new   Mutex ();

     public void  拆弹()
    {
         Thread  t =  new   Thread (炸弹内部);
        t.Start();
    }

     private void  炸弹内部()
    {
        m.WaitOne();
        热度++;
         Thread .Sleep(1000);
         if  (热度>1)
        {
             Console .WriteLine( "炸弹爆炸!拆弹手见马克思..." );
            m.ReleaseMutex();
             return ;
        }
        热度--;
         Console .WriteLine( "炸弹安全拆除!拆弹手这个月奖金加倍..." );
        m.ReleaseMutex();
    }
}


拆弹手很幸运,这个月奖金加倍了。如果把Mutex去掉,那么马克思就等着他们去聊天。

信号量-Semaphore


互斥锁和同步都是锁定一个资源,同时只让一个线程去操作。 
对于可以允许限定数量线程执行的情况互斥锁就不适合了,这里就需要信号量。 
信号量通过一个计数器来控制对共享资源的访问,如果计数器的闲置数大于0,那么就允许访问,如果=0就拒绝访问。

 public  Semaphore( int  initialCount,  int  maximumCount);

initialCount:可以同时授予的信号量的初始请求数。 
maximumCount:可以同时授予的信号量的最大请求数。

 public virtual bool  WaitOne();
 public int  Release();

WaitOne():阻止当前线程,直到当前 System.Threading.WaitHandle 收到信号。 
Release():退出信号量并返回前一个计数。 

下面还是请出我们杯具的拆弹手来演示。

 class   Program
 {
     static void  Main( string [] args)
    {
         //有关部门的砖家叫兽告诉拆弹手炸弹最多4个人同时拆
          Int32  拆弹手人数 = 4;
         炸弹  b =  new   炸弹 (拆弹手人数);
         while  (拆弹手人数 > 0)
        {
            b.拆弹();
            拆弹手人数--;
        }
         Console .Read();
    }
}
 public class   炸弹
 {
     private   Int32  最高温度 = 0;
     private   Int32  热度 = 0;
     private   Semaphore  S;

     public  炸弹( Int32  limit)
    {
        最高温度 = 3;
        S =  new   Semaphore (limit, limit);
    }

     public void  拆弹()
    {
         Thread  t =  new   Thread (炸弹内部);
        t.Start();
    }

     private void  炸弹内部()
    {
        S.WaitOne();
        热度++;
         Thread .Sleep(1000);
         if  (热度 > 最高温度)
        {
             Console .WriteLine( "炸弹爆炸!拆弹手见马克思..." );
            S.Release();
             return ;
        }
        热度--;
         Console .WriteLine( "炸弹安全拆除!拆弹手这个月奖金加倍..." );
        S.Release();
    }
}

杯具的拆弹手,这里砖家叫兽错误指出最多4个人,而炸弹最高支持3个人!唉。。。

  

使用事件实现-幸福的小新


事件是另外一种同步对象,ManualResetEvent,AutoResetEvent2个类实现了事件同步的功能,都派生自EventWaitHandle类。 

介绍下ManualResetEvent。

 public  ManualResetEvent( bool  initialState);
 public virtual bool  WaitOne();
 public bool  Reset();
 public bool  Set();


第一个是构造函数,传入的变量是事件是否发出信号。 
第二个是等待一个事件发出信号,期间是阻塞的。 
第三个是重置事件为未发出信号状态。 
最后一个是设置事件为发出信号状态。 

ManualResetEvent和AutoResetEvent的主要实现都是相同,只有一点不同,就是ManualResetEvent需要手动设置事件为未发出信号,而AutoResetEvent是自动设置的。 

野原新之助的一天

 class   Program
 {
     static void  Main( string [] args)
    {
         ManualResetEvent  mal =  new   ManualResetEvent ( false );
         美女姐姐  美女 =  new   美女姐姐 ();
         小新  新之助 =  new   小新 ();
         Thread  t1 =  new   Thread ( new   ParameterizedThreadStart (美女.美女姐姐上街));
         Thread  t2 =  new   Thread ( new   ParameterizedThreadStart (新之助.小新出动));
        t1.Start(mal);
        t2.Start(mal);
         Console .Read();
    }

     public class   美女姐姐
     {
         public void  美女姐姐上街( object  Mal)
        {
             Thread .Sleep(2000);
             Console .WriteLine( "青春美丽的美女姐姐上街了..." );
             Thread .Sleep(1000);
            (( ManualResetEvent )Mal).Set();
        }
    }

     public class   小新
     {
         public  小新()
        {
             Thread .Sleep(1000);
             Console .WriteLine( "小新拿着奶茶,猥琐的躲在大街边的绿化带里..." );
             Thread .Sleep(1000);
        }

         public void  小新出动( object  Mal)
        {
             ManualResetEvent  Mal1 = ( ManualResetEvent )Mal;
             Console .WriteLine( "小新左右寻找美女姐姐..." );
             //等待美女姐姐的出现
              Mal1.WaitOne();
             Console .WriteLine( "小新跑到美女姐姐面前,脱下小裤裤,亮出大象,开始跳大象舞..." );
             Console .WriteLine( "屁股扭扭,“大象,大象,大象...”" );
            Mal1.Reset();
        }
    }
}


不解释了。。。 

总结下吧!


写了这么多,应该好好思考下这些同步方式,每种虽然大概思路是一样!但是绝对有各自的特点。 
有空大家还是看看CLR 3版中的线程核心部分,里面把这些同步的原理讲的很清楚。 
总之线程的水太深,慢慢游吧,下一篇把剩下的一些线程同步方式讲下,然后就在最后对NET线程同步做个总结。

作者:海不是蓝 
博客: hailan2012  
邮箱:hailan2012@sina.com 
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

随笔分类 -多线程编程

NET多线程探索-互斥锁,信号量,事件(小新和拆弹部队友情演出) 2012-03-22 17:14 by 海不是蓝, 835 visits,  网摘 ,  收藏 ,  编辑

 

4 Comment Categories:  多线程编程 Tags:  多线程 ,  线程同步

NET多线程探索-线程同步和通信 2012-03-20 16:53 by 海不是蓝, 1157 visits,  网摘 ,  收藏 ,  编辑

 

5 Comment Categories:  多线程编程 Tags:  多线程 ,  同步 ,  线程通信

NET多线程探索-NET线程基础知识点 2012-03-19 13:40 by 海不是蓝, 216 visits,  网摘 ,  收藏 ,  编辑

 

0 Comment Categories:  .NET Framework ,  多线程编程 Tags:  多线程

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于mutex互斥锁的详细内容...

  阅读:30次

上一篇: HttpClient介绍

下一篇:程序员的修养