深入多线程之:用Wait与Pulse模拟一些同步构造的应用详解
你可能在上篇文章中《深入多线程之:双向信号与竞赛的用法分析》注意到了这个模式:两个Waiting 循环都要下面的构造:
lock(_locker)
{
while(!_flag) Monitor.Wait(_locker);
_flag = false;
}
在这里_flag被另一线程设置为true。这是,从作用上讲,这里在模仿AutoResetEvent。如果我们将 _flag = false;去掉,那么我们就得到了一个基本的ManualResetEvent.
让我们使用Wait和Pulse来为ManualResetEvent完成剩余的代码吧。
readonly object _locker = new object();
bool _signal;
void WaitOne()
{
lock (_locker)
{
while (!_signal) Monitor.Wait(_locker);
}
}
void Set()
{
lock (_locker) { _signal = true; Monitor.PulseAll(_locker); }
}
void Reset() { lock (_locker) _signal = false; }
在这里使用PulseAll,是因为可能有很多阻塞的线程。
如果在WaitOne方法中增加_signal=false就可以简单的模拟AutoResetEvent.例如:
void WaitOne()
{
lock (_locker)
{
while (!_signal) Monitor.Wait(_locker);
_signal = false; //实现自动关闭功|能
}
}
然后在Set方法中,将PulseAll修改为Pulse
Lock(_locker) {_signal = true; Monitor.Pulse(_locker);}
如果使用的是int类型的_signal 标志,那么我们可以得到一个最基本的Semaphore.
Waiting Queues and PulseAll
当多余一个线程在同一个对象上面等待的时候,一个 “等待队列(waiting queue)” 就形成了。
每一次调用Pulse都会释放在”等待队列”头部的一个线程。下面的图形象的展示了这一点:
线程调用Monitor.Enter 进入ReadyQueue. 等待获取锁,成功获取锁后,如果正常的执行,那么之后会调用Monitor.Exit退出,
否则如果获取了锁之后发现需要等待其他的线程或者是其他阻塞条件,那么调用Wait方法,就进入了等待队列,
当等待的线程完成并调用Pulse后,处在WaitingQueue头部的线程就被 Pulse了,等待CPU调度 。之后再次进入Ready Queue,重新获取锁。
Countdown
借助Wait和Pulse,我们可以实现CountdownEvent的主要功能。例如:
class Countdown
{
object _locker = new object();
int _value; //使用_value来计数
public Countdown() { }
public Countdown(int initialCount) { _value = initialCount; }
public void Singnal() { AddCount(-1); } //将计数减一
public void AddCount(int amount)
{
lock (_locker)
{
_value += amount; //将计数增加或减少
if (_value <= 0) Monitor.PulseAll(_locker);//如果value<=0,说明所有等待的任务都完成了。
}
}
public void Wait()
{
lock (_locker)
{
//只要计数 > 0 就等待。
while (_value > 0)
{
Monitor.Wait(_locker);
}
}
}
}
这和我们上次的代码几乎一致,只是这次我们的阻塞条件基于一个整型_value标志。
相关文章
- 这篇文章主要介绍了C#中sleep和wait的区别分析,有助于深入理解C#中线程的原理与使用技巧,非常具有实用价值,需要的朋友可以参考下...2020-06-25
- 这篇文章主要介绍了ASP.Net中的async+await异步编程的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
详解C#中 Thread,Task,Async/Await,IAsyncResult的那些事儿
本文主要介绍了C#中 Thread,Task,Async/Await,IAsyncResult的相关知识。具有一定的参考价值,下面跟着小编一起来看下吧...2020-06-25python实习总结(yeild,async,azwait和协程)
今天是Python实习的第一天,熟悉了环境,第一次使用macbook,氛围还不错,努力学习新知识,希望本片文章能给你带来帮助...2021-10-08- 这篇文章主要介绍了关于async和await的一些误区实例详解,有助于更加深入的理解C#程序设计,需要的朋友可以参考下...2020-06-25
- 本篇文章主要介绍了说说C#的async和await的具体用法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
- 这篇文章主要介绍了浅谈C#中的Async和Await的用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25
- 这篇文章主要给大家介绍了如何通过一篇文章弄懂C#中async和await的相关资料,async和await相信大家应该不陌生,让异步处理变得更友好,本文通过示例代码介绍的非常详细,需要的朋友可以参考下...2021-07-01
- 这篇文章主要介绍了ASP.NET 应用程序实际使用过程中的一些总结, 包括 异常捕获 、 死锁 、 应用程序崩溃 ,实际使用过程中一不注意就可能掉坑里了...2021-09-22
- 本篇文章是对Wait与Pulse的使用进行了详细的分析介绍,需要的朋友参考下...2020-06-25
.NET中的async和await关键字使用及Task异步调用实例
这篇文章主要介绍了.NET中的async和await关键字使用及Task异步调用实例,本文还包含了取消执行和显示进度的例子,需要的朋友可以参考下...2020-06-25- async表示异步,而await可以看作async wait,个人对async与await的简单理解就是,我们可以用同步的方式去书写异步代码,这篇文章主要给大家介绍了关于JS中如何优雅的使用async await的相关资料,需要的朋友可以参考下...2021-10-05
- 这篇文章主要介绍了c# SpinWait的相关资料,帮助大家更好的理解和学习c# 编程,感兴趣的朋友可以了解下...2020-12-08
- 以下是对pthread_cond_wait的用法进行了详细的分析介绍,需要的朋友可以过来参考下...2020-04-25
- 这篇文章主要介绍了c# 在Emit代码中如何await一个异步方法,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下...2021-03-23
浅谈Async和Await如何简化异步编程(几个实例让你彻底明白)
本篇文章主要介绍了浅谈Async和Await如何简化异步编程,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25- 这篇文章主要介绍了解决await在forEach中不起作用的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-02-25
- 这篇文章主要介绍了C#中的Async和Await用法,包括在C#5.0下一些新特性的影响,需要的朋友可以参考下...2020-06-25
- 本篇文章对async and await 的入门基础操作进行了详细的分析介绍,需要的朋友参考下...2020-06-25
- 这篇文章主要介绍了浅谈C# async await 死锁问题总结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-10-13