是否为了获取锁()担保要求?

2023-09-02 21:25:58 作者:离笙

当多个线程对同一对象请求锁,请问CLR保证锁将在他们被要求的顺序被收购?

我写了一个测试,看看如果这是真的,这似乎预示着,是的,​​但我不知道这是明确的。

 类LockSequence
{
    私人静态只读对象_lock =新的对象();

    私有静态的DateTime _dueTime;

    公共静态无效测试()
    {
        VAR状态=新的名单,其中,国家>();

        _dueTime = DateTime.Now.AddSeconds(5);

        的for(int i = 0;我小于10;我++)
        {
            VAR状态=新的国家{指数= I};
            ThreadPool.QueueUserWorkItem(转至,状态);
            states.Add(州);
            Thread.sleep代码(100);
        }

        states.ForEach(S => s.Sync.WaitOne());
        states.ForEach(S => s.Sync.Close());
    }

    私有静态无效围棋(对象状态)
    {
        VAR S =(州)的状态;

        Console.WriteLine(围棋进:+ s.Index);

        锁(_lock)
        {
            Console.WriteLine({0,2}有锁,s.Index);
            如果(_dueTime> DateTime.Now)
            {
                VAR时间= _dueTime  -  DateTime.Now;
                Console.WriteLine({0,2}沉睡{1}蜱,s.Index,time.Ticks);
                Thread.sleep代码(时间);
            }
            Console.WriteLine({0,2}退出锁,s.Index);
        }

        s.Sync.Set();
    }

    私有类国家
    {
        公众诠释指数;
        公共只读ManualResetEvent的同步=新的ManualResetEvent(假);
    }
}
 

打印:

  

围棋进入: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退出锁定

解决方案

IIRC,它的很可能的是按照这个顺序,但它不能保证。我认为至少有理论上的情况下,一个线程将被唤醒不合逻辑,请注意,它仍然没有锁,并进入队列的后面。这是可能的,这只是对等待 / 通知,但我有一个偷渡怀疑它是为锁定为好。

Mysql学习笔记 锁

我绝对将不依赖于它 - 如果你需要的东西出现在一个序列,建立一个问答LT; T> 或类似的话。

编辑:我刚刚发现这个在乔·达菲的在Windows 并发编程基本上同意:

  

由于显示器内部使用内核对象,它们表现出相同的大致-FIFO的行为,该操作系统的同步机制还表现出(在previous章中的说明)。显示器是不公平的,因此,如果另一个线程试图之前唤醒等待线程试图获取锁获取锁,偷偷摸摸的线程被允许获取锁。

在大致先进先出位我在想什么之前,而偷偷摸摸线程位为进一步的证据,你不应该做出的FIFO排序的假设。

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);
    }
}

Prints:

Go entered: 0

0 got lock

0 sleeping for 49979998 ticks

Go entered: 1

Go entered: 2

Go entered: 3

Go entered: 4

Go entered: 5

Go entered: 6

Go entered: 7

Go entered: 8

Go entered: 9

0 exiting lock

1 got lock

1 sleeping for 5001 ticks

1 exiting lock

2 got lock

2 sleeping for 5001 ticks

2 exiting lock

3 got lock

3 sleeping for 5001 ticks

3 exiting lock

4 got lock

4 sleeping for 5001 ticks

4 exiting lock

5 got lock

5 sleeping for 5001 ticks

5 exiting lock

6 got lock

6 exiting lock

7 got lock

7 exiting lock

8 got lock

8 exiting lock

9 got lock

9 exiting lock

解决方案

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.

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

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

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.

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.

相关推荐