Monitor.TryEnter(lock1, TimeSpan.FromSeconds(5))
该方法是检查锁对象在指定时间内是否释放资源,如果释放则返回true否则false
下面是死锁的例子:(大家复制到自己VS中跑一下,我给的是完整控制台代码,打断点调试一下,结合着我的注释,写的很详细。应该会理解的。)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using static System.Console;
using static System.Threading.Thread;
namespace _9.Monitor类锁定资源
{
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(1000);
//监视器.TryEnter允许不被卡住,在指定的超时时间过后返回false
WriteLine("Monitor.TryEnter allows not to get stuck,returning false after a specified timeout is elapsed");
//判断当前锁的对象是否释放,超时就代表还未释放。
if (Monitor.TryEnter(lock1, TimeSpan.FromSeconds(5)))
{
//成功获取受保护的资源
WriteLine("cquired a protected resoured resource succesfully");
}
else
{
//获取资源超时
WriteLine("Timeout acquiring a resource!");
}
}
new Thread(()=> { LockTooMuch(lock1, lock2); }).Start();
WriteLine("---------------------------");
lock (lock2)//-----------------此时主线程已经锁死lock2
{
//这是一个死锁
WriteLine("This will be a deadlock");
Sleep(1000);
lock (lock1) //=============主线程等待子线程释放lock1
{
//已成功获取受保护的资源
WriteLine("Acquired a protected resource succesfully");
}
}
}
//上下俩段注释对比发现 主线程的lock2锁死导致子线程无法释放lock1 因为子线程在等待着主线程释放lock2 此时就造成了死锁。
static void LockTooMuch(object lock1 ,object lock2)
{
lock (lock1)//=============子线程已经锁死lock1
{
Sleep(1000);
lock (lock2); //----------------子线程等待着主线程的lock2释放 子线程处于等待状态
}
}
}
}
大概解释一下:(一定要自己跑一遍,打断点调试。)
先看 看 LockTooMuch 方法。 在 该 方法 中 我们 先 锁定 了 第一个 对象, 等待 一秒 后 锁定 了 第二个 对象。 然后 在另 一个 线程 中 启动 该 方法。 最后 尝试 在 主 线程 中 先后 锁定 第二个 和 第一个 对象。 如果 像 该 示例 的 第二 部分 一样 使用 lock 关键字, 将会 造成 死锁。 第一个 线程 保持 对 lock1 对象 的 锁定, 等待 直到 lock2 对象 被 释放。 主线 程 保持 对 lock2 对象 的 锁定 并 等待 直到 lock1 对象 被 释放, 但 lock1 对象 永远 不会 被 释放。 实际上 lock 关键字 是 Monitor 类 用 例 的 一个 语法 糖。 如果 我们 分解 使用 了 lock 关键字 的 代码, 将会 看到 它 如下 面 代码 片段 所示:
bool acquiredLock = false;
try
{
访问受锁保护的资源的代码
Monitor.Enter(lockObject, ref acquiredLock);
//Code that accesses resources that are protected by the lock
}
finally
{
if (acquiredLock)
{
Monitor.Exit(lockObject);
}
}
因此, 我们 可以 直接 使用 Monitor 类。 其 拥有 TryEnter 方法, 该 方法 接受 一个 超时 参数。 如果 在 我们 能够 获取 被 lock 保护 的 资源 之前, 超时 参数 过期, 则 该 方法 会 返回 false。