我怀疑"图书馆"下面的方法实际上会起作用,或者最终会死锁。
我有一个" old"需要保护的对象," 锁定 "似乎是最好的工具,因为在整个"类"中有一些对此资源的重新调用( SomeSharedResource )。
修改
1。)打电话给" Compute"实际阻止或更糟糕的情况死锁?
var finalResult = await Compute(3).ConfigureAwait(false); // will this block?
2。)如果有人这样做怎么样?
var finalResult = Compute(3).Result; // will this block/deadlock?
3。)2个线程同时呼叫:
var finalResult = await Compute(3).ConfigureAwait(false); // will this block?
有问题的方法:
private readonly object lockObject = new object();
private async Task<double> Compute(int input)
{
double result;
lock (lockObject) {
result = SomeSharedResource(input);
}
return await ComputeAsync(result).ConfigureAwait(false); // some other awaitable method
}
答案 0 :(得分:2)
对Compute(int input)
的调用当然可以阻止。您lock (lockobject)
以同步方式。如果一个线程持有lockObject而另一个线程尝试获取它,则第二个线程将在等待第一个线程完成时阻塞。
出于与#1相同的原因,这可能会阻止。它不会基于我们在此处看到的内容死锁,因为结果延续不会继承同步上下文。它还会阻止同步等待ComputeAsync()
的结果,因为它使用了.Result
出于与#1相同的原因,这可能会阻止。
锁定和延续是不同的概念。虽然我不能保证你的程序不会陷入僵局,但这是因为我无法看到你的整个程序。你在这里展示的任何东西都没有乞求陷入僵局(当然,除了.Result
之外的典型警告。)
但是要认识到lock()的存在实际上是在宣告阻塞执行线程的可能性。 async
- await
个关键字在某些同步执行的代码中锁定不会产生任何魔力。
答案 1 :(得分:2)
这些问题都没有实际答案。他们的答案都是“是的,如果有足够的操作条件,它们就会陷入僵局”。
如果你的意思是“lock
语句会导致阻塞还是死锁?”,那么阻塞的答案是肯定的,而死锁的答案是肯定的(假设SomeSharedResource(input)
表现良好,即不内部僵局。
答案 2 :(得分:1)
对于问题1,2和3,答案是,&#34;他们可能不会遇到死锁&#34; 。但是,对lock
部分的多个同时调用将会阻塞,因为它们无法同时执行,这并不意味着它们会死锁。
您需要检查lock
内发生的事情以确定。
如果lock
内的函数产生阻塞异步调用(await
或等效函数),最终会回调Compute()
或其他同时锁定lockObject
的代码,则会产生危险。 1}}。
只要lock
中的所有函数都没有阻塞另一个线程,你应该是安全的。如果存在阻止异步调用,则需要验证他们不会重新进入,或确保不阻止它们。
以下是一些做什么的例子,而不是做:
private async Task<double> DoSomething()
{
return await Compute(0);
}
private readonly object lockObject = new object();
private async Task<double> Compute(int input)
{
double result;
lock (lockObject) {
//This would be bad.
result = await DoSomething();
//So would this. If you didn't wait inside the lock you wouldn't deadlock though.
var t = DoSomething();
result = t.Result;
//This would be okay because it doesn't call back to Compute()
using (var stream = File.OpenText("test.txt"))
{
var contents = await stream.ReadToEndAsync();
}
}
return await ComputeAsync(result).ConfigureAwait(false); // some other awaitable method
}