互斥体与互锁 <第五篇>
互斥体实现了“互相排斥”(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的区别:
- Monitor不是waitHandle的子类,它具有等待和就绪队列的实际应用;
- Monitor无法跨进程中实现线程同步,但是Mutex可以;
- 相对而言两者有明显的性能差距,mutex相对性能较弱但是功能更为强大,monitor则性能比较好;
- 两者都是用锁的概念来实现同步不同的是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)); }
}

互斥体与互锁 <第五篇>的更多相关文章
- 转载 互斥体与互锁 <第五篇>
互斥体实现了“互相排斥”(mutual exclusion)同步的简单形式(所以名为互斥体(mutex)).互斥体禁止多个线程同时进入受保护的代码“临界区”.因此,在任意时刻,只有一个线程被允许进入这 ...
- 【APUE】信号量、互斥体和自旋锁
http://www.cnblogs.com/biyeymyhjob/archive/2012/07/21/2602015.html http://blog.chinaunix.net/uid-205 ...
- 【uTenux实验】互斥体
互斥体,维基百科中交互斥锁.其定义是这样的:互斥锁(英语:英语:Mutual exclusion,缩写 Mutex)是一种用于多线程编程中,防止两条线程同时对同一公共资源(比如全局变量)进行读写的机制 ...
- mysql第五篇 : MySQL 之 视图、触发器、存储过程、函数、事物与数据库锁
第五篇 : MySQL 之 视图.触发器.存储过程.函数.事物与数据库锁 一.视图 视图是一个虚拟表(非真实存在的),其本质是‘根据SQL语句获取动态的数据集,并为其命名‘ ,用户使用时只需使用“名称 ...
- boost 互斥体和锁
1.共享资源是一个自动锁住的房间,互斥体是钥匙,进入房间必须取钥匙,离开房间应该还钥匙.这就对应着互斥体的lock(取钥匙)和unlock(还钥匙). 2.考虑下面的场景:还钥匙的时候出现异常,会发生 ...
- 多线程(三)多线程同步_基本介绍及mutex互斥体
同步进制的引入为了解决以下三个主要问题:1.控制多个线程之间对共享资源访问,保证共享资源的完整性例如:线程A对共享资源进行写入,线程B读取共享资源2.确保多个线程之间的动作以指定的次序发生例如:线程B ...
- 第五篇 Replication:事务复制-How it works
本篇文章是SQL Server Replication系列的第五篇,详细内容请参考原文. 这一系列包含SQL Server事务复制和合并复制的详细内容,从理解基本术语和设置复制的方法,到描述它是如何工 ...
- linux 内核的rt_mutex (realtime互斥体)
linux 内核有实时互斥体(锁),名为rt_mutex即realtime mutex.说到realtime一定离不开priority(优先级).所谓实时,就是根据优先级的不同对任务作出不同速度的响应 ...
- 基元线程同步构造之 Mutes(互斥体)
互斥体实现了“互相排斥”(mutual exclusion)同步的简单形式(所以名为互斥体(mutex)). 互斥体禁止多个线程同时进入受保护的代码“临界区”(critical section). 因 ...
随机推荐
- 这样就算会了PHP么?-10
关于基本的文件读写内容: <?php echo "readfile function:<br>"; readfile("tm.txt"); e ...
- ps2keyboard demo code for 8052
#pragma code symbols debug objectextend #include <reg51.h> /* special function register declar ...
- UML--一些图
通过UML来表示汽车,简洁明了. 统一建模语言--UML. 参与者Actor,参与者代表了现实世界的人.人. 用例use case,就是参与者要做什么并且获得什么.事. 业务场景,用例场景.规则. 业 ...
- Eclipse-cdt 配合 gdbserver 进行 arm 程序远程调试 下
上一篇中,介绍了如何编译.运行arm-linux-gdb 和 gdbserver,这一篇中介绍怎样结合Eclipse-cdt进行图形化编译调试 首先当然是使用CDT创建项目并添加源文件. 在左侧 Pr ...
- C++初始化列表问题
C++初始化列表问题,类中有一个对象类型的数组成员变量,在初始化列表中初始化时报错“[]”操作符语法错误 class ClassA{private ClassB arrayOfObjectClassB ...
- 2014.11.12模拟赛【最小公倍数】| vijos1047最小公倍数
最小公倍数(lcm.c/.cpp/.pas) 题目描述 给定两个正整数,求他们的最小公倍数. 样例输入 28 12 样例输出 84 数据范围 对于40%数据:1<=a,b<=10^9 对于 ...
- thinkjs初试
背景 什么是thinkjs?thinkjs是奇舞团开源的一款NodejsMVC框架,该框架底层基于Promise来实现,很好的解决了Nodejs里异步回调的问题.我为什么会使用thi ...
- 构建高性能WEB站点笔记二
构建高性能WEB站点笔记 因为是跳着看的,后面看到有提到啥epoll模型,那就补充下前面的知识. 第三章 服务器并发处理能力 3.2 CPU并发计算 进程 好处:cpu 时间的轮流使用.对CPU计算和 ...
- FlexComboBoxTree
在我的CSDN资源中有项目工程文件.下载导入工程即可看到效果,下面是地址. http://download.csdn.net/detail/cym_lmy/6326053 MyCombBoxTree1 ...
- Merlin 的魔力: SpringLayout 管理器
摘自http://tech.it168.com/a2009/0211/265/000000265087_all.shtml 摘自http://cache.baiducontent.com/c?m=9f ...