Man*_*ndo 1 c# multithreading synchronization
我要求一部分代码一次只能由一个线程运行(单个资源锁定).
lock(object)C#中的语句允许这样做.但是,它不会保留对锁的请求顺序.
例如,考虑下面的100个线程启动,其中编号的线程尝试按顺序锁定挂锁:
for (int i = 0; i < 100; i++)
{
(new Thread(delegate(object index)
{
int name = (int) index;
byte[] len = new byte[2];
Console.WriteLine(string.Format("Thread:{0} going for lock. ",
name));
lock (padlock)
{
rnd.GetBytes(len);
ushort l = BitConverter.ToUInt16(len, 0);
Console.WriteLine(string.Format("Thread:{0} sleeping: {1}",
name, l));
Thread.Sleep(l);
}
})).Start(i);
Run Code Online (Sandbox Code Playgroud)
实际授予访问权限的顺序并不完美(1-> 100)或NOT FIFO.然而,似乎确实存在"早期早期"EIEO模式(可能由堆运行?).
问题是:什么决定了锁定授予顺序,是否可以依赖于不使不幸的线程挨饿?
更新:这个答案解释了它.这是相关的引用(Joe Duffy在Windows上的并发编程):
因为监视器在内部使用内核对象,所以它们表现出与OS同步机制也表现出的相同的粗略FIFO行为(在前一章中描述).监视器是不公平的,因此如果另一个线程试图在唤醒的等待线程尝试获取锁之前获取锁,则允许偷偷摸摸的线程获取锁.
Servy的答案当然是正确的.一些额外的细节:
是什么决定了锁定授予顺序?
最终,操作系统.
是不是可以依赖不饿的一个不幸的线程?
饥饿不太可能,但可能.如果你不能忍受很小的饥饿机会,你需要一些比锁更复杂的东西.
我还注意到锁是"不公平的",因为你可以在锁中有一个线程,八个线程在等待,锁中的线程离开,一个没有等待的第十个线程请求锁并获得它"切断线".Joe给出了一个有趣的分析,为什么Windows现在在这里使用"不公平"的锁定分配策略,如果这个主题让你感兴趣:
http://joeduffyblog.com/2006/12/14/anticonvoy-locks-in-windows-server-2003-sp1-and-windows-vista/
| 归档时间: |
|
| 查看次数: |
829 次 |
| 最近记录: |