除了Lock()、Monitor之外,我们最长用的就是Mutex了,但是玩不好Mutex就总会造成死锁或者AbandonedMutexException(我就玩的不怎么好,在并发性访问测试的时候总是遇到关于Mutex的问题,各位线虫见笑了,不过还是把我遇到的一些问题和总结拿出来和大家分享,有误的地方还往指正。

还是先举一个简单的例子,来说明一下这个东西:

   public class ThreadMutex

{

public void Test()

{

Thread t1 = new Thread(Thread1);

Thread t2 = new Thread(Thread2);

t1.Start();

t2.Start();

}

public void Thread1()

{

Mutex m = new Mutex(false, "test");

bool b2 = m.WaitOne();

Console.WriteLine("Thread1 get the mutex : " + b2);

Thread.Sleep(10000);

m.ReleaseMutex();

}

public void Thread2()

{

Mutex m = new Mutex(false, "test");

bool b2 = m.WaitOne();

Console.WriteLine("Thread2 get the mutex : " + b2);

Thread.Sleep(1000);

m.ReleaseMutex();

}

}

恩,Thread1中Mutex.WaitOne()后,就想到与Thread1拿到了Mutex所有权,这时Thread2得到了同样的Mutex,然后Mutex.WaitOne(),也想拿到Mutex的所有权,这时就必须等待了。这里只需要两点就能明白什么是Mutex了:

1.   Mutex是一个令牌,当一个线程拿到这个令牌时运行,另外想拿到令牌的线程就必须等待,直到拿到令牌的线程释放令牌。没有所有权的线程是无法释放令牌的。

2.   Mutex(false,”string”)中的string是令牌的关键,或者可以叫令牌名,因为Mutex是跨进程的,整个系统中只会有唯一的令牌存在所以,也就是说你在一个应用程序中的一个线程中得到了Mutex的所有权,那在另外一个线程中的另外的线程想得到他就必须要等待。

 

要弄清楚Mutex就还需要弄清楚两个很重要的问题:

1.那就是Mutex是调用的Win32 的API

HANDLE CreateMutex(

LPSECURITY_ATTRIBUTES lpMutexAttributes,

BOOL bInitialOwner,

LPCTSTR lpName

);

这就是他为什么能跨进程访问的原因,正是由于它使用P/Invoke,他的效率问题就凸现出来,明显不如Monitor之类的快,用的时候还需多多斟酌。

下面放一个Mutex的简单实现,看看Mutex在.net下是如何实现的。

 

2.Mutex的生命周期,这个问题让我郁闷了很久,因为不太了解Mutex的机制,使得我也没法弄清楚到底能活多长时间,这也是AbandonedMutexException经常会出现的原因。还是先来看一段程序:

  public class ThreadMutex

{

public void Test()

{

Thread t1 = new Thread(Thread1);

Thread t2 = new Thread(Thread2);

t1.Start();

t2.Start();

}

public void Thread1()

{

Mutex m = new Mutex(false, "test");

bool b2 = m.WaitOne();

Console.WriteLine("Thread1 get the mutex : " + b2);

}

public void Thread2()

{

Thread.Sleep(10);//保证Thread1执行完

Mutex m = new Mutex(false, "test");

bool b2=m.WaitOne();

Console.WriteLine(b2);

m.ReleaseMutex();

}

}

在Thread2中的WaitOne()方法就会报错了,AbandonedMutexException,原因就是Thread1拿到了Mutex后没有释放,Thread1就结束了,这样Mutex成了被抛弃的地孩子了,呵呵。但是如果垃圾收集了,就不一样咯。代码稍微修改了一下:

  public class ThreadMutex

{

public void Test()

{

Thread t1 = new Thread(Thread1);

Thread t2 = new Thread(Thread2);

t1.Start();

t2.Start();

}

public void Thread1()

{

Mutex m = new Mutex(false, "test");

bool b2 = m.WaitOne();

Console.WriteLine("Thread1 get the mutex : " + b2);

}

public void Thread2()

{

Thread.Sleep(10);//保证Thread1执行完

GC.Collect();

GC.WaitForPendingFinalizers();

bool b1;

Mutex m = new Mutex(false, "test",out b1);

Console.WriteLine(b1);

bool b2=m.WaitOne();

Console.WriteLine(b2);

m.ReleaseMutex();

}

}

结果是:

Thread1 get the mutex : True

True

True

Thread2里面的Mutex是新创建的,呵呵,这里面的玄妙自己体会吧。

最后要说一下的是Mutex的访问和window访问文件的机制基本上是一样的,window访问对象和访问文件使用的是同样的安全机制(虽然我还没看懂)。

线程、同步与锁——Mutex想说爱你不容易相关推荐

  1. 多线程:C#线程同步lock,Monitor,Mutex,同步事件和等待句柄(上)

    多线程:C#线程同步lock,Monitor,Mutex,同步事件和等待句柄(上) 转自 http://www.cnblogs.com/freshman0216/archive/2008/07/27/ ...

  2. Java核心(三)并发中的线程同步与锁

    2019独角兽企业重金招聘Python工程师标准>>> 乐观锁.悲观锁.公平锁.自旋锁.偏向锁.轻量级锁.重量级锁.锁膨胀...难理解?不存的!来,话不多说,带你飙车. 上一篇介绍了 ...

  3. 秒杀多线程第七篇 经典线程同步 互斥量Mutex

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event& ...

  4. Java 多线程和并发编程:(二)线程同步 Lock 锁

    线程同步 Lock 锁 1.Lock 锁 2.步骤 3.Lock 与 synchronized 的区别 1.Lock 锁 Lock 锁:对需要上锁的地方上锁 JDK1.5 后新增的功能 与 Synch ...

  5. 线程同步----递归锁

    概述 最常见的进程/线程的同步方法有互斥锁(或称互斥量Mutex),读写锁(rdlock),条件变量(cond),信号量(Semophore)等.在Windows系统中,临界区(Critical Se ...

  6. 线程同步(互斥锁、条件、读写锁、信号量)

    参考:(四十三)线程--线程同步(互斥锁.读写锁.条件变量.信号量) 作者:FadeFarAway 发布时间:2017-01-17 21:25:28 网址:https://blog.csdn.net/ ...

  7. iOS开发线程同步技术-锁

    概览 1,什么是锁(临界区)? 2,常用的锁有哪些? 3,相关链接 什么是锁(临界区) 临界区:指的是一块对公共资源进行访问的代码,并非一种机制或是算法. 常用的锁有哪些? 互斥锁:是一种用于多线程编 ...

  8. 开线程插数据_python笔记7-多线程之线程同步(锁lock)

    前言丨 关于吃火锅的场景,小伙伴并不陌生,前面几章笔记里面我都有提到,今天我们吃火锅的场景: 吃火锅的时候a同学往锅里下鱼丸,b同学同时去吃掉鱼丸,有可能会导致吃到生的鱼丸. 为了避免这种情况,在下鱼 ...

  9. 经典线程同步 互斥量Mutex的使用分析

    互斥量(mutex)内核对象用来确保一个线程独占对一个资源的访问. 互斥量对象包含一个使用计数.线程ID以及一个递归计数. 互斥量与关键段的行为完全相同.但是,互斥量是内核对象,而关键段是用户模式下的 ...

最新文章

  1. Unity提高工作效率的终极指南
  2. 使用指针统计字符串中的数字字符的个数
  3. avrstudio5 拨码管
  4. ole db 访问接口 sqlncli 无法启动分布式事务_阿里终面:分布式事务原理
  5. C++使用GDI+实现图片格式转换
  6. python羊车门问题_羊车门问题的python模拟和解释
  7. hdu 3183 A Magic Lamp(给一个n位的数,从中删去m个数字,使得剩下的数字组成的数最小(顺序不能变),然后输出)...
  8. SpringBoot加itext实现PDF导出
  9. python处理pdf实例_python 使用pdfminer3k 读取PDF文档的例子
  10. 游戏编程新手教程:怪物AI设计简述
  11. 新浪微博推出具有中国特色的“关注但屏蔽”功能
  12. 新功能:阿里云负载均衡SLB支持HTTP访问强制跳转HTTPS
  13. 非常优秀的swiper插件————幻灯片播放、图片轮播
  14. excel 公式 单引号 concat_Recovery for Excel(Excel文件修复工具)下载 v6.0官方版-
  15. 逆向Mac版WPS2019解除版本过期限制
  16. XML文档类型定义---XML Schema结构
  17. ArcEngine实现动态加载地图
  18. Flutter系列(二)flutter项目打安装包
  19. STC51入门笔记(郭天祥C语言)---第二节:Keil 软件使用及流水灯设计
  20. 广州蔬菜配送公司如何做,食材配送生意如何起步?这些行业内容你要知道

热门文章

  1. codeforces 160A-C语言解题报告
  2. Android Glide图片加载框架(二)源码解析之into()
  3. 如何在三个月内获得三年的工作经验
  4. 开发者成功学:扔掉你那些很sexy的想法
  5. 评论:电商巨头们谁有勇气晒晒“价格战”账单?
  6. 高速率AVS整数变换的汇编实现与优化
  7. git 图形化工具 GitKraken 的使用 —— 分支的创建与合并
  8. Docker : Dockerfile 定制镜像
  9. shader飞线改进版
  10. html5 下拉刷新(pc+移动网页源码)