Con*_*ngo 2 .net c# multithreading thread-safety threadpool
我已经编写了很多多线程C#代码,并且我从未在我发布的任何代码中遇到过死锁.
我使用以下经验法则:
lock
关键字(我也使用其他技术,如读取器/写入器锁,但很少,只有在速度需要时).Interlocked.Increment
如果我正在处理long
.long
,dictionary
或list
.我想知道如果这些规则是拇指一直遵循,甚至可能产生死锁,如果是这样,代码会是什么样子?
更新
我也使用这些经验法则:
TimeSpan
.object _lockDict = new object();
然后lock(_lockDict) { // Access dictionary here }
.更新
Jon Skeet的精彩回答.它还证实了为什么我永远不会遇到死锁,因为我倾向于本能地避免嵌套锁,即使我使用它们,我总是本能地保持入口顺序一致.
并且在回应我关于倾向于仅使用lock
关键字的评论时,即使用Dictionary
+ lock
代替ConcurrentDictionary
,Jon Skeet发表了这样的评论:
@Contango:这正是我采取的方法.我会去寻找简单的代码,每次锁定"聪明的"无锁代码,直到有证据表明它引起了问题.
是的,它很容易死锁,没有实际访问任何数据:
private readonly object lock1 = new object();
private readonly object lock2 = new object();
public void Method1()
{
lock(lock1)
{
Thread.Sleep(1000);
lock(lock2)
{
}
}
}
public void Method2()
{
lock(lock2)
{
Thread.Sleep(1000);
lock(lock1)
{
}
}
}
Run Code Online (Sandbox Code Playgroud)
通话双方Method1
并Method2
在大致相同的时间,和繁荣-死锁.每个线程都将等待"内部"锁定,另一个线程已将其作为其"外部"锁定获取.
如果你确保你总是以相同的顺序获得锁(例如" lock2
除非你已经拥有,否则永远不会获得" lock1
)并以相反的顺序释放锁(如果你正在获取/释放,这是隐含的lock
)那么你就不会得到一种僵局.
你可以仍然得到与异步代码僵局,在与有关单个线程-但涉及Task
,以及:
public async Task FooAsync()
{
BarAsync().Wait(); // Don't do this!
}
public async Task BarAsync()
{
await Task.Delay(1000);
}
Run Code Online (Sandbox Code Playgroud)
如果你从WinForms线程运行该代码,你将在一个线程中死锁 - FooAsync
将阻塞返回的任务BarAsync
,并且BarAsync
由于等待返回到UI线程而无法继续运行.基本上,您不应该从UI线程发出阻塞调用...
归档时间: |
|
查看次数: |
354 次 |
最近记录: |