我不清楚(并且找不到足够清晰的文档):在异步方法中使用lock关键字时:如果对象已被阻止,线程是否会被阻塞,或者它是否会以挂起状态返回任务(不是阻塞线程,并在释放锁时返回?)
在下面的代码中,该行会阻塞线程吗?如果它阻塞线程(这是我的想法),是否有标准的阻塞解决方案?我正在考虑使用AsyncLock,但首先我想尝试标准的东西。
感谢。
private object myLock = new object();
private async Task MyMethod1(){
lock (myLock ) {// <---- will this line cause a return of the current method as an Await method call would do if myLock was already locked.
....
}
}
// other methods that lock on myLock
答案 0 :(得分:35)
在下面的代码中,该行会阻塞线程吗?
从技术上讲,是的,但它不会像你期望的那样工作。
有两个原因可以解释为什么线程仿射锁与async
不能很好地配合。一个是(在一般情况下),async
方法可能无法在同一个线程上恢复,因此它将尝试释放它不拥有的锁,而另一个线程永远持有锁。另一个原因是在持有锁的await
期间,在锁定时可以执行任意代码。
出于这个原因,编译器不再允许在await
块内禁止lock
表达式。不过,你仍然可以直接使用Monitor
或其他原语拍摄自己。
如果它阻塞了线程(这是我的想法),是否有标准的非阻塞解决方案?
是; SemaphoreSlim
类型支持WaitAsync
。
答案 1 :(得分:6)
这是不允许停止僵局(即开发人员伤害自己)。我发现的最佳解决方案是使用信号量 - See this post for details。
相关代码摘录:
running build_ext
building 'pycocotools._mask' extension
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\amd64\cl.exe /c /nologo /Ox /MD /W3 /GS- /DNDEBUG -IE:\Anaconda2\Lib\site-packages\numpy\core\include -I../common -IE:\Anaconda2\include -IE:\Anaconda2\PC /Tcpycocotools/_mask.c /Fobuild\temp.win-amd64-2.7\Release\pycocotools/_mask.obj -Wno-cpp -Wno-unused-function -std=c99
cl : Command line error D8021 : invalid numeric argument '/Wno-cpp'
error: command 'C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\BIN\\amd64\\cl.exe' failed with exit status 2
答案 2 :(得分:4)
不,不会。
lock
是Monitor.Enter
和Monitor.Exit
的语法糖。 lock
将继续执行该方法,直到锁定被释放。它在任何方式,形状或形式上都不像await
那样。
答案 3 :(得分:2)
您的任务不会以暂停状态返回。它会等到myLock解锁后才能在lock语句中运行代码。无论您使用什么C#异步模型,都会发生这种情况。
换句话说,没有两个线程能够在锁内运行语句。除非,myLock对象有许多不同的实例。