lock() 是否保证按请求的顺序获得? [英] Does lock() guarantee acquired in order requested?

查看:24
本文介绍了lock() 是否保证按请求的顺序获得?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

When multiple threads request a lock on the same object, does the CLR guarantee that the locks will be acquired in the order they were requested?

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

I wrote up a test to see if this was true, and it seems to indicate yes, but I'm not sure if this is definitive.

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 滴答

0 sleeping for 49979998 ticks

进入:1

进入:2

进入:3

进入:4

进入:5

进入:6

进入:7

进入:8

进入:9

0 退出锁定

1 被锁定

1 睡眠 5001 滴答声

1 sleeping for 5001 ticks

1 个退出锁

2 被锁定

2 睡眠 5001 滴答声

2 sleeping for 5001 ticks

2 退出锁

3 被锁定

3 睡眠 5001 滴答声

3 sleeping for 5001 ticks

3 退出锁

4 被锁定

4 睡眠 5001 滴答声

4 sleeping for 5001 ticks

4 退出锁

5 被锁定

5 睡眠 5001 滴答声

5 sleeping for 5001 ticks

5 退出锁

6 被锁定

6 退出锁

7 被锁定

7 退出锁

8 被锁定

8 退出锁

9 被锁定

9 退出锁

推荐答案

IIRC,很有可能按这个顺序排列,但不能保证.我相信至少在理论上存在一个线程会被虚假唤醒的情况,注意它仍然没有锁,然后走到队列的后面.这可能仅适用于 Wait/Notify,但我偷偷怀疑它也适用于锁定.

IIRC, it's highly likely to be in that order, but it's not guaranteed. I believe there are at least theoretically cases where a thread will be woken spuriously, note that it still doesn't have the lock, and go to the back of the queue. It's possible that's only for Wait/Notify, but I have a sneaking suspicion it's for locking as well.

肯定不会依赖它 - 如果您需要按顺序发生,请建立一个 Queue<T> 或类似的东西.

I definitely wouldn't rely on it - if you need things to occur in a sequence, build up a Queue<T> or something similar.

我刚刚在 Joe Duffy 的 Concurrent基本同意的Windows编程:

I've just found this within Joe Duffy's Concurrent Programming on Windows which basically agrees:

因为监视器在内部使用内核对象,所以它们表现出与操作系统同步机制也表现出的大致相同的 FIFO 行为(在前一章中描述).监视器是不公平的,因此如果另一个线程在唤醒的等待线程尝试获取锁之前尝试获取锁,则允许偷偷摸摸的线程获取锁.

Because monitors use kernel objects internally, they exhibit the same roughly-FIFO behavior that the OS synchronization mechanisms also exhibit (described in the previous chapter). Monitors are unfair, so if another thread tries to acquire the lock before an awakened waiting thread tries to acquire the lock, the sneaky thread is permitted to acquire a lock.

大致 FIFO"位是我之前想到的,而偷偷摸摸的线程"位进一步证明了您不应该对 FIFO 排序做出假设.

The "roughly-FIFO" bit is what I was thinking of before, and the "sneaky thread" bit is further evidence that you shouldn't make assumptions about FIFO ordering.

这篇关于lock() 是否保证按请求的顺序获得?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆