首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >锁()保证是否按所要求的顺序获得?

锁()保证是否按所要求的顺序获得?
EN

Stack Overflow用户
提问于 2010-11-19 19:57:16
回答 5查看 15K关注 0票数 70

当多个线程请求同一个对象上的锁时,CLR是否保证按照请求的顺序获取锁?

我写了一个测试,看看这是不是真的,这似乎表明是的,但我不确定这是否确定。

代码语言:javascript
运行
复制
class LockSequence
{
    private static readonly object _lock = new object();

    private static DateTime _dueTime;

    public static void Test()
    {
        var states = new List<State>();

        _dueTime = DateTime.Now.AddSeconds(5);
        
        for (int i = 0; i < 10; i++)
        {
            var state = new State {Index = i};
            ThreadPool.QueueUserWorkItem(Go, state);
            states.Add(state);
            Thread.Sleep(100);
        }
        
        states.ForEach(s => s.Sync.WaitOne());
        states.ForEach(s => s.Sync.Close());
    }

    private static void Go(object state)
    {
        var s = (State) state;

        Console.WriteLine("Go entered: " + s.Index);

        lock (_lock)
        {
            Console.WriteLine("{0,2} got lock", s.Index);
            if (_dueTime > DateTime.Now)
            {
                var time = _dueTime - DateTime.Now;
                Console.WriteLine("{0,2} sleeping for {1} ticks", s.Index, time.Ticks);
                Thread.Sleep(time);
            }
            Console.WriteLine("{0,2} exiting lock", s.Index);
        }

        s.Sync.Set();
    }

    private class State
    {
        public int Index;
        public readonly ManualResetEvent Sync = new ManualResetEvent(false);
    }
}

指纹:

进入:0 0锁 0睡49979998只蜱 进入:1 进入:2 进入:3 进入:4 进入:5 进入:6 进入:7 进入:8 进入:9 0退出锁 1把锁 1只睡5001只蜱 1出锁 2门锁定 2只睡5001只蜱 2退出锁 3锁 3只睡5001只蜱 3出锁 4锁 4只睡5001只蜱 4出锁 5把锁 5只睡5001只蜱 5出锁 6把锁 6出锁 7把锁 7出口锁 8把锁 8出锁 9把锁 9出口锁

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2010-11-19 19:59:48

IIRC,这很有可能是按这个顺序进行的,但不能保证。我相信至少在理论上,线程会被伪造地唤醒,注意它仍然没有锁,然后转到队列的后面。这可能只适用于Wait/Notify,但我有一种潜移默化的怀疑,它也是用来锁定的。

我绝对不会依赖它--如果您需要在一个序列中发生一些事情,那么构建一个Queue<T>或类似的东西。

编辑:我刚刚在乔·达菲的Windows环境下的并发编程中发现了这一点,它基本上同意:

由于监视器在内部使用内核对象,因此它们表现出与OS同步机制(在前一章中描述)大致相同的FIFO行为。监视器是不公平的,因此,如果另一个线程在唤醒等待线程试图获取锁之前试图获取该锁,则允许该秘密线程获取一个锁。

“粗略的FIFO”位是我以前想过的,而“狡猾的线程”位进一步证明了你不应该对FIFO排序做出假设。

票数 81
EN

Stack Overflow用户

发布于 2015-06-01 21:46:14

正常的CLR锁不能保证是FIFO。

但是,有一个这个答案中的QueuedLock类 将提供一个有保证的FIFO锁定行为

票数 14
EN

Stack Overflow用户

发布于 2010-11-19 20:11:18

lock语句是用来使用Monitor类来实现其行为的,而Monitor类的文档没有提到(我可以找到的)公平性。因此,您不应依赖按请求顺序获取的请求锁。

事实上,Jeffery Richter的一篇文章指出,实际上lock是不公平的:

  • .NET CLR中的线程同步公平性

当然--这是一篇老掉牙的文章,所以事情可能已经发生了变化,但考虑到Monitor类的合同中没有关于公平性的承诺,你需要假设最坏的情况。

票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4228864

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档