互斥体实现了“互相排斥”(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. 这样就算会了PHP么?-10

    关于基本的文件读写内容: <?php echo "readfile function:<br>"; readfile("tm.txt"); e ...

  2. ps2keyboard demo code for 8052

    #pragma code symbols debug objectextend #include <reg51.h> /* special function register declar ...

  3. UML--一些图

    通过UML来表示汽车,简洁明了. 统一建模语言--UML. 参与者Actor,参与者代表了现实世界的人.人. 用例use case,就是参与者要做什么并且获得什么.事. 业务场景,用例场景.规则. 业 ...

  4. Eclipse-cdt 配合 gdbserver 进行 arm 程序远程调试 下

    上一篇中,介绍了如何编译.运行arm-linux-gdb 和 gdbserver,这一篇中介绍怎样结合Eclipse-cdt进行图形化编译调试 首先当然是使用CDT创建项目并添加源文件. 在左侧 Pr ...

  5. C++初始化列表问题

    C++初始化列表问题,类中有一个对象类型的数组成员变量,在初始化列表中初始化时报错“[]”操作符语法错误 class ClassA{private ClassB arrayOfObjectClassB ...

  6. 2014.11.12模拟赛【最小公倍数】| vijos1047最小公倍数

    最小公倍数(lcm.c/.cpp/.pas) 题目描述 给定两个正整数,求他们的最小公倍数. 样例输入 28 12 样例输出 84 数据范围 对于40%数据:1<=a,b<=10^9 对于 ...

  7. thinkjs初试

    背景          什么是thinkjs?thinkjs是奇舞团开源的一款NodejsMVC框架,该框架底层基于Promise来实现,很好的解决了Nodejs里异步回调的问题.我为什么会使用thi ...

  8. 构建高性能WEB站点笔记二

    构建高性能WEB站点笔记 因为是跳着看的,后面看到有提到啥epoll模型,那就补充下前面的知识. 第三章 服务器并发处理能力 3.2 CPU并发计算 进程 好处:cpu 时间的轮流使用.对CPU计算和 ...

  9. FlexComboBoxTree

    在我的CSDN资源中有项目工程文件.下载导入工程即可看到效果,下面是地址. http://download.csdn.net/detail/cym_lmy/6326053 MyCombBoxTree1 ...

  10. Merlin 的魔力: SpringLayout 管理器

    摘自http://tech.it168.com/a2009/0211/265/000000265087_all.shtml 摘自http://cache.baiducontent.com/c?m=9f ...