互斥体实现了“互相排斥”(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将会话保存在数据库里

    php默认把会话保存在临时文件中,保存在数据库中可以提高安全性,在共享主机服务器上,所有web站点都使用同一个临时目录,这意味着数十个程序都在同一位置进行文件读取的操作,我们很容易就编写一个脚本从这个 ...

  2. c# 编程添加控件

    Button b = new Button();//创建一个新的按钮 b.Text = "test"; //添加到panel1中 panel1.Controls.Add(b);

  3. 脚本控制向Android模拟拨打电话,发送短信,定位设置功能

    做行为触发的时候要向模拟器实现拨打电话,发送短信,定位设置的的功能,可以很方便通过telnet localhost  5554实现. 写个脚本很快的搞定了.网上资料很多,脚本的很少,也所积点德啦. 写 ...

  4. IOS 监听通讯录是否改变

    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error); ABAddressBookRegist ...

  5. [Cycle.js] From toy DOM Driver to real DOM Driver

    This lessons shows how we are able to easily swap our toy DOM Driver with the actual Cycle.js DOM Dr ...

  6. mvc 5 的过滤器和webapi 过滤器 对应实现的action过滤器区别

     asp.net webapi  Action过滤器实现这个: #region 程序集 System.Web.Http, Version=5.2.3.0, Culture=neutral, Publi ...

  7. SELECT TOP column FROM table [ORDER BY column [DESC]]

    如果想返问表中行的子集,仅需要返回特定数量的记录,而不管符合条件的行有多少.要返回排在前面的值,可以有两个选择:指定固定数量的行,或者指定总行数的百分比.SQL Server不对这些数据做任何分析,共 ...

  8. 0128——手势Gesture

    UIGestureRecognizer: 1.locationinView 获取手势在某个视图里面的坐标位置 2.delegate监听手势的行为 3.state状态 开始:UIGestureRecog ...

  9. Ubuntu13.04手动安装nvidia显卡驱动

    1. 下载最新版的nVidia驱动,命名为NVIDIA.run. http://www.nvidia.com/page/drivers.html 2.编辑blacklist.conf. sudo ge ...

  10. 优化DOM交互

    DOM操作与交互要消耗大量时间,所以优化DOM交互有重大意义. 1.最小化现场更新 如果需要访问的DOM部分是已经显示的页面的一部分,那么这就是在进行一个现场更新.现场更新得越多,代码完成执行所需要的 ...