《C#多线程编程实战》1.11 Monitor.TryEnter()避免死锁
这章的内容是真的有意思
特别是代码。
先贴上代码:
class Program
{
static void Main(string[] args)
{
object lock1 = new object(); object lock2 = new object(); new Thread(() => LockTooMuch(lock1, lock2)).Start(); lock(lock2)
{
Thread.Sleep(); Console.WriteLine("Monitor.TryEnter allow not to get stuck,returning false after a specified timer is elapsed"); if(Monitor.TryEnter(lock1,5))
{
Console.WriteLine("Acquired a protected resource succesfully"); }
else
{
Console.WriteLine("Timerout cquiring a resource"); }
} new Thread(() => LockTooMuch(lock1, lock2)).Start(); lock (lock2)
{
Console.WriteLine("This will be deadlock");
Thread.Sleep();
lock (lock1)
{
Console.WriteLine("Acquired a protected resource succesfully");
} }
Console.ReadKey();
}
static void LockTooMuch(object Lock1,object Lock2)
{
lock(Lock1)
{
Thread.Sleep(1); lock (Lock2)
{ } }
}
}
说实话,这章代码,我一开始没看明白。真的。
有些时候真的就是难者不会会者不难。
咱慢慢来来说。
咱先从这一部分开始:
static void LockTooMuch(object Lock1,object Lock2)
{
lock(Lock1)
{
Thread.Sleep(); lock (Lock2)
{ } }
}
这一部分的代码很好理解:
传入两个引用类型的object参数。
然后是代码主要部分先是
锁死lock1
然后再lock1里面锁死lock2.
这个部分的锁死的代码,也就意味着解锁的顺序,lock1等待lock2执行完毕才会解锁lock1.
本章说避免锁死。那么什么是锁死?
那么我们来原书的代码:
new Thread(() => LockTooMuch(lock1, lock2)).Start();
lock (lock2)
{
Console.WriteLine("This will be deadlock");
Thread.Sleep();
lock (lock1)
{
Console.WriteLine("Acquired a protected resource succesfully");
}
}
这一部分的代码加上静态的LockTooMatch的方法运行就会锁死。
我们按照这个思路清理一下代码:
static void Main(string[] args)
{
object lock1 = new object(); object lock2 = new object(); new Thread(() => LockTooMuch(lock1, lock2)).Start(); lock (lock2)
{
Console.WriteLine("This will be deadlock");
Thread.Sleep();
lock (lock1)
{
Console.WriteLine("Acquired a protected resource succesfully");
} }
Console.ReadKey();
}
static void LockTooMuch(object Lock1,object Lock2)
{
lock(Lock1)
{
Thread.Sleep(); lock (Lock2)
{ } }
}
see
永远锁死
为什么只会执行到这里呢?
Console.WriteLine("This will be deadlock");
一步一步的
首先程序新开线程运行LockTooMuch,然后再主线程锁LOCK2输出内容,线程等待1S之后再锁LOCK1 在输出语句。
lock (lock2)
{
Console.WriteLine("This will be deadlock");
Thread.Sleep();
lock (lock1)
{
Console.WriteLine("Acquired a protected resource succesfully");
} }
按照我们之前说的东西,L2必须等待L1结束才会释放。
这是主线程的部分。
下面是方法的部分
static void LockTooMuch(object Lock1,object Lock2)
{
lock(Lock1)
{
Thread.Sleep(); lock (Lock2)
{ } }
}
同样也是L1等待L2的结束才会是否。
主线程和新开线程是同时的。
也就是会有竞争。
那么执行的顺序是什么呢?
很简单
主线程新开线程
主线锁LOCK2
新开线程执行锁LOCK1
主线程输出
新开线程等待1s
主线程等待1s
新开线程锁LOCK2但是失败
主线程锁LOCK1但是失败
程序停止继续向下运行
为什么主线程,新线程锁LOCK为什么会失败呢?
新开线程锁lock2会失败是因为主线程在用lock2而且还没有用完。
主线程锁lock1会失败是应为新开线程做用lock1还么有用完。
所以会锁死。
ok 我们知道锁死的原因,下面我们通过Monitor.TryEnter来避免锁死。
Monitor.TryEnter是作用什么呢?
TryEnter有三个重载方法。
常用的是带有等待时间的。
作用就是在规定的时间去尝试解锁资源,或者获取资源。如果获取成功就返回true,不成功就返回false。这个代码总会返回结果。超时也会返回不过是false,也就说锁死了也会有办法来处理,不会尴尬的停在那里了
我们看看代码:
new Thread(() => LockTooMuch(lock1, lock2)).Start(); lock(lock2)
{
Thread.Sleep(); Console.WriteLine("Monitor.TryEnter allow not to get stuck,returning false after a specified timer is elapsed"); if(Monitor.TryEnter(lock1,5))
{
Console.WriteLine("Acquired a protected resource succesfully"); }
else
{
Console.WriteLine("Timerout cquiring a resource"); }
}
ok 清理下会锁死的代码,来运行代码
执行了else内的代码,说明尝试解锁lock1失败了,和上面那个会死锁的代码一样的结果,但是这个却可以继续持续其他代码,不会卡在死锁的部分。
我们来看看执行的过程【大家可以在VS中 使用断点,逐语句等方式来观察线程的运行顺序】
主线程新开线程
主线锁LOCK2
新开线程执行锁LOCK1
主线程等待1s
新开线程等待1s
主线程输出语句
新开线程锁LOCK2但是失败
主线程尝试解锁LOCK1,5s内。(成功返回true 失败返回fasle 超时返回false)但是失败
主线程输出else内容
程序结束
执行的顺序和死锁的顺序差不多,但是结果却不一样的因为Monitor.TryEnter避免的死锁的尴尬地步,程序多线程中出现死锁,使用monitor.tryenter会很好的避免死锁。
《C#多线程编程实战》1.11 Monitor.TryEnter()避免死锁的更多相关文章
- C#多线程编程实战(二)
1.1 简介 为了防止一个应用程序控制CPU而导致其他应用程序和操作系统本身永远被挂起这一可能情况,操作系统不得不使用某种方式将物理计算分割为一些虚拟的进程,并给予每个执行程序一定量的计算能力.此外操 ...
- Java多线程编程实战指南(核心篇)读书笔记(五)
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76730459冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...
- ASP.Net教程系列:多线程编程实战(一)
Web开发中使用多线程可以增强用户体验,尤其是多用户.多任务.海量数据和资源紧张的情况下.所以我们的ASP.Net教程设立多线程编程实战专题.下面这些代码范例都是入门级的,希望对对大家学习ASP.Ne ...
- Java多线程编程实战读书笔记(一)
多线程的基础概念本人在学习多线程的时候发现一本书——java多线程编程实战指南.整理了一下书中的概念制作成了思维导图的形式.按照书中的章节整理,并添加一些个人的理解.
- Java多线程编程实战指南(核心篇)读书笔记(四)
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76690961冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...
- Java多线程编程实战指南(核心篇)读书笔记(三)
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76686044冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...
- Java多线程编程实战指南(核心篇)读书笔记(二)
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76651408冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...
- Java多线程编程实战指南(核心篇)读书笔记(一)
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76422930冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...
- 《Java多线程编程实战指南(核心篇)》阅读笔记
<Java多线程编程实战指南(核心篇)>阅读笔记 */--> <Java多线程编程实战指南(核心篇)>阅读笔记 Table of Contents 1. 线程概念 1.1 ...
随机推荐
- idea完成分支和主干的合并
我们在开发一个项目的时候,我们可能会创建一个分支和一个主干.对于分支而言,我们一般在开发的时候可能会使用,但是在项目上线的时候,我们抽取的项目的地址可能是主干的svn地址,这时我们需要将分支上的svn ...
- ARM-Linux移植之(三)——init进程启动流程分析
我们通常使用Busybox来构建根文件系统的必要的应用程序.Busybox通过传入的参数来决定执行何种操作.当init进程启动时,实际上调用的是Busybox的init_main()函数,下面我们来分 ...
- 温故而知新java事务
一.什么是Java事务 通常的观念认为,事务仅与数据库相关. 事务必须服从ISO/IEC所制定的ACID原则.ACID是原子性(atomicity).一致性(consistency).隔离性 (iso ...
- maven项目如何启动运行---发布到tomcat中
前面两篇文章: 新建maven框架的web项目 以及 将原有项目改成maven框架 之后,我们已经有了maven的项目 那么 maven项目到底怎么启动呢 如果我们直接在myeclipse中按以前的启 ...
- win7下cygwin 中 root用户的设置
问题描述: cygwin 在 win10下安装完成后使用当前用户登录后看所在磁盘的文件权限是没有问题的,但在cygwin编译出来的文件的权限为空,这个问题可以使用以下方法来解决: 解决办法: 将cyg ...
- sql 2008 权限角色控制
Use Test --创建角色 create role rtt create user username for login username --将用户TestUser添加到TestRole角色中 ...
- Table Tennis Game 2
Description Misha and Vanya have played several table tennis sets. Each set consists of several serv ...
- JasperMES.cn JasperMES.com.cn 我的MES网站
好久没有更新博客园.今天写上两面的两个网址JasperMES.cn JasperMES.com.cn是想记录我在做上面两个网站时的一点心得. 老实说,现在建站的软件很多,WordPress,CMS,我 ...
- Objective-C 基础语法log打印那些事儿(一)
Objective-C 基础语法详解 雨松MOMO原创文章如转载,请注明:转载至我的独立域名博客雨松MOMO程序研究院,原文地址:http://www.xuanyusong.com/archives/ ...
- Windows下查询指定端口进程,并杀死
1. 找到指定端口的进程号 c:\devworks\lib\httpd-2.4.10-win32-VC9\Apache24\bin>netstat -ano|findstr "9000 ...