Lock内部调用的就是Monitor
其实lock在IL代码中会被翻译成Monitor。
也就是Monitor.Enter(obj)和Monitor.Exit(obj).
lock(obj)
{
}
等价为:
try
{
Monitor.Enter(obj)
}
catch()
{}
finally
{
onitor.Exit(obj)
}
主要说Monitor的两个方法,wait()和pause()
在lock代码里面如果调用了Monitor.Wait(),会放弃对资源的所有权,让别的线程lock进来。然后别的线程代码里Pulse一下(让原线程进入到等待队列),然后在Wait一下释放资源,这样原线程的就可以继续执行了(代码还堵塞在wait那句话呢)。
也就是说,必须两个或多个线程共同调用Wait和Pulse,把资源的所有权抛来抛去,才不会死锁。
线程主要有三种状态
①runing
②wait
③ready
- pulse(obj)用于将线程从wait状态跟改为ready状态,当此线程执行完成时,或者此线程状态更改为wait时,将从ready状态中选择执行
- wait(obj),将线程从runing状态更改为wati状态,若要继续执行,需要先更改为ready状态
static void Main(string[] args)
{
object obj = new object();
Task.Run(() => {
lock (obj)
{
Console.WriteLine("lockA");
Thread.Sleep(1000);
//此线程状态更改为wait,进入阻塞状态
Monitor.Wait(obj);
Monitor.Pulse(obj);
}
Console.WriteLine("Aover");
});
Task.Run(() => {
lock (obj)
{
Console.WriteLine("lockB");
Thread.Sleep(500);
Monitor.Pulse(obj);
Monitor.Wait(obj);
}
Console.WriteLine("Bover");
});
结果:
lockA
lockB
Aover
Bover
两个线程间踢皮球
A->B->A-B
Thread.Join()
Thread.Join()相当于task.wait(); 阻塞当前线程,等待任务完成。和AutoEvent相似是处理同步关系的,但是AutoEvent是跨进程的,而Monitor是针对线程的。
本文深入探讨了C#中Monitor类的使用方法及其与lock关键字的关系,解析了线程状态转换机制,包括runing、wait和ready状态,并通过代码示例展示了Monitor.Wait()和Monitor.Pulse()如何实现线程间的资源传递,避免死锁。

被折叠的 条评论
为什么被折叠?



