本文介绍了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 行为(在前一章中描述).监视器是不公平的,因此如果另一个线程在唤醒的等待线程尝试获取锁之前尝试获取锁,则允许偷偷摸摸的线程获取锁.

大致 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() 是否保证按请求的顺序获得?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-28 06:11