互斥体实现了“互相排斥”(mutual exclusion)同步的简单形式(所以名为互斥体(mutex))。互斥体禁止多个线程同时进入受保护的代码“临界区”。因此,在任意时刻,只有一个线程被允许进入这样的代码保护区。

  任何线程在进入临界区之前,必须获取(acquire)与此区域相关联的互斥体的所有权。如果已有另一线程拥有了临界区的互斥体,其他线程就不能再进入其中。这些线程必须等待,直到当前的属主线程释放(release)该互斥体。什么时候需要使用互斥体呢?互斥体用于保护共享的易变代码,也就是,全局或静态数据。这样的数据必须通过互斥体进行保护,以防止它们在多个线程同时访问时损坏。

1、Mutex

  Mutex是一个同步基元,它与前面提到的锁最大的区别在于它支持进程间同步。

  Mutex允许同一个线程多次重复访问共享区,但是对于别的线程那就必须等待,它甚至支持不同进程中的线程同步,这点更能体现他的优势,但是劣势也是显而易见的,那就是巨大的性能损耗和容易产生死锁的困扰,所以除非需要在特殊场合,否则 我们尽量少用为妙,这里并非是将Mutex的缺点说的很严重,而是建议大家在适当的场合使用更为适合的同步方式,Mutex 就好比一个重量型的工具,利用它则必须付出性能的代价。

  1、Mutex线程同步

  Mutex实现线程同步主要依靠以下两个方法实现:

  • WaitOne 阻止当前线程,直到当前 WaitHandle 收到信号。
  • ReleaseMutex 释放 Mutex 一次。
    class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
ThreadPool.QueueUserWorkItem(Run);
} Console.Read();
} static int count = 0; static Mutex mutex = new Mutex(); static void Run(object obj)
{
//阻止当前线程
mutex.WaitOne(); Console.WriteLine("当前数字:{0}", ++count); //释放 Mutex
mutex.ReleaseMutex();
}
}

  输出:

  

  Mutex和Monitor的区别:

  1. Monitor不是waitHandle的子类,它具有等待和就绪队列的实际应用;
  2. Monitor无法跨进程中实现线程同步,但是Mutex可以;
  3. 相对而言两者有明显的性能差距,mutex相对性能较弱但是功能更为强大,monitor则性能比较好;
  4. 两者都是用锁的概念来实现同步不同的是monitor一般在方法(函数)调用方加锁;mutex一般在方法(函数)内部加锁,即锁定被调用端;

  2、进程间同步

  当给Mutex取名的时候能够实现进程同步,不取名实现线程同步。

  Mutex有两种类型:未命名的局部mutex和已命名的系统mutex。

  • 本地mutex仅存在与进程当中,进程内可见;
  • 已命名的系统mutex在整个操作系统中可见,可用于同步进程活动;
    class Program
{
static void Main(string[] args)
{
//使用线程输出等待状态
Thread t1 = new Thread(ShowMyWord);
t1.Start(); Run(t1); Console.Read();
} static int count = 0; static Mutex mutex = new Mutex(false, "xxoo"); static void Run(Thread t1)
{ //这个WaitOne方法要么返回true,要么一直不返回(不会返回false),所以没办法用if来判断
//于是,用个线程输出等待状态
mutex.WaitOne(); Console.WriteLine("终于轮到老子了! " + DateTime.Now.TimeOfDay.ToString());
//停止线程t1,不要再输出等待状态
t1.Abort();
//模拟干活十秒
Thread.Sleep(10000);
Console.WriteLine("干完! " + DateTime.Now.TimeOfDay.ToString()); //释放 Mutex
mutex.ReleaseMutex();
} static void ShowMyWord(object obj)
{
for (int i = 0; i < 10; i++)
{
Thread.Sleep(2000);
Console.WriteLine("我的心在等待,一直在等待! " + DateTime.Now.TimeOfDay.ToString());
}
}
}

  以上代码,将生成的.exe文件复制两份:

  

  快速运行两个输出如下:

  

二、Interlocked

  实际引用中,可能我们对共享变量的使用并不十分复杂,可能只是一些简单的操作如:自增、自减、求和、赋值、比较等。

  MSDN中的解析Interlocked为多个线程共享的变量提供原子操作。

  常用操作如下:

方法 说明
Add 相加
CompareExchange 比较
Increment 递增
Decrement 递减
Exchange 赋值

  示例:

   class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 20; i++)
{
Thread t = new Thread(Run); t.Start();
} Console.Read();
} static int Incre = 0;
static int Add = 0;
static int Exchange = 0;
static int Decre = 21;
static int CompareExchange = 0; static Mutex mutex = new Mutex(); static void Run()
{
//自增操作
//Console.WriteLine("当前数字:{0}", Interlocked.Increment(ref Incre));
//递减操作
//Console.WriteLine("当前数字:{0}", Interlocked.Decrement(ref Decre));
//相加
//Console.WriteLine("当前数字:{0}", Interlocked.Add(ref Add,10));
//赋值
//Console.WriteLine("当前数字:{0}", Interlocked.Exchange(ref Exchange, 5));
//比较,如果第三个参数等于CompareExchange,则将第二个参数的值,赋给第一个参数
Console.WriteLine("当前数字:{0}", Interlocked.CompareExchange(ref CompareExchange, 15,0)); }
}

互斥体与互锁 <第五篇>的更多相关文章

  1. 转载 互斥体与互锁 <第五篇>

    互斥体实现了“互相排斥”(mutual exclusion)同步的简单形式(所以名为互斥体(mutex)).互斥体禁止多个线程同时进入受保护的代码“临界区”.因此,在任意时刻,只有一个线程被允许进入这 ...

  2. 【APUE】信号量、互斥体和自旋锁

    http://www.cnblogs.com/biyeymyhjob/archive/2012/07/21/2602015.html http://blog.chinaunix.net/uid-205 ...

  3. 【uTenux实验】互斥体

    互斥体,维基百科中交互斥锁.其定义是这样的:互斥锁(英语:英语:Mutual exclusion,缩写 Mutex)是一种用于多线程编程中,防止两条线程同时对同一公共资源(比如全局变量)进行读写的机制 ...

  4. mysql第五篇 : MySQL 之 视图、触发器、存储过程、函数、事物与数据库锁

    第五篇 : MySQL 之 视图.触发器.存储过程.函数.事物与数据库锁 一.视图 视图是一个虚拟表(非真实存在的),其本质是‘根据SQL语句获取动态的数据集,并为其命名‘ ,用户使用时只需使用“名称 ...

  5. boost 互斥体和锁

    1.共享资源是一个自动锁住的房间,互斥体是钥匙,进入房间必须取钥匙,离开房间应该还钥匙.这就对应着互斥体的lock(取钥匙)和unlock(还钥匙). 2.考虑下面的场景:还钥匙的时候出现异常,会发生 ...

  6. 多线程(三)多线程同步_基本介绍及mutex互斥体

    同步进制的引入为了解决以下三个主要问题:1.控制多个线程之间对共享资源访问,保证共享资源的完整性例如:线程A对共享资源进行写入,线程B读取共享资源2.确保多个线程之间的动作以指定的次序发生例如:线程B ...

  7. 第五篇 Replication:事务复制-How it works

    本篇文章是SQL Server Replication系列的第五篇,详细内容请参考原文. 这一系列包含SQL Server事务复制和合并复制的详细内容,从理解基本术语和设置复制的方法,到描述它是如何工 ...

  8. linux 内核的rt_mutex (realtime互斥体)

    linux 内核有实时互斥体(锁),名为rt_mutex即realtime mutex.说到realtime一定离不开priority(优先级).所谓实时,就是根据优先级的不同对任务作出不同速度的响应 ...

  9. 基元线程同步构造之 Mutes(互斥体)

    互斥体实现了“互相排斥”(mutual exclusion)同步的简单形式(所以名为互斥体(mutex)). 互斥体禁止多个线程同时进入受保护的代码“临界区”(critical section). 因 ...

随机推荐

  1. 11g Rac 切换

    <pre name="code" class="sql">[grid@devrac1 ~]$ crsctl status res -t ------ ...

  2. Azure Storage Client Library 重试策略建议

    有关如何配置 Azure Storage Library 重试策略的信息,可参阅 Gaurav Mantri 撰写的一篇不错的文章<SCL 2.0 – 实施重试策略>.但很难找到关于使用何 ...

  3. SCOI2014省选总结

    这一次省选,主要是抱着玩的心态去的,如同高二的那些大神高一的心态一样,只记得在省选之前我们一直在说,这一次我们的目标,就是不爆0,最后也如愿以偿的实现了. 首先,请允许我吐槽一下day1.....da ...

  4. AsyncTask实现登录功能,上传图片,get,post

    提交成功时,从服务器端返回数据“load success” 用户名.密码正确后成功登录,并且在服务器端的文件保存目录上看到了从客户端上传的图片. 客户端代码: MainActivity.java im ...

  5. 重载operator new实现检测内存泄漏是否可行

    行与不行,就凭我这水平,说出来未免显示太过自大.不还,我还想根据自己的代码来讨论这个问题. 重载operator new来检测内存只的办法,那就是在new的时候记录指针地址及文件名.行号,在delet ...

  6. UGUI 帧动画插件

    最近在开发一款功夫猫游戏,本来使用Unity Sprite制作,但是发现Sprite对各种分辨率不支持. 看着游戏很简单就使用UGUI制作,在中途发现有很多帧动画播放,使用了Animation调整使用 ...

  7. Hook linux 网络封包

    要注册一个hook函数需要用到nf_register_hook()或者nf_register_hooks()系统API和一个struct nf_hook_ops{}类型的结构体对象 一个简单的demo ...

  8. HTML与CSS入门——第一章 理解Web的工作方式

    知识点: 1.万维网的简史 2."网页"的含义,以及该术语不能反映所涉及的所有内容的原因 3.如何从你的个人计算机进入别人的浏览器 4.选择Web托管提供商的方法 5.不同的Web ...

  9. ASP.NET 后台下载文件方法

    void DownLoadFile(string fileName) { string filePath = Server.MapPath(fileName);//路径 //以字符流的形式下载文件 F ...

  10. border-radius讲解2

    一:border-radius只有一个取值时,四个角具有相同的圆角设置,其效果是一致的: .demo { border-radius: 10px; } 其等价于: .demo{ border-top- ...