You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET中等待lock语句的线程是否按阻塞顺序进入锁?

C# lock语句是否保证线程按到达顺序获取锁?

我尚未针对该问题做过专门测试,但在其他需要此行为的测试中,我发现阻塞在lock语句上的线程似乎确实按到达锁代码段的顺序进入锁。这只是我的运气,还是该行为确实有保证?


更新

实际上,通过以下代码我已确认,使用lock()语句无法保证线程的有序执行。

public static void Main()
{
    Object objLock = new Object();

    Stopwatch perf = new Stopwatch();
    foreach (var batch in Enumerable.Range(1, 20))
    {
        perf.Restart();

        var sequence = Enumerable.Range(1, 200);
        var tickets = new List<int>();
        var threads = sequence.Select(item =>
        {
            var thread = new Thread(() =>
            {
                lock (objLock)
                {
                    tickets.Add(item);
                    Thread.Sleep(50);
                }
            });

            Thread.Sleep(10);

            thread.Start();
            return thread;
        }).ToArray();

        foreach (var thread in threads) thread.Join();

        Console.WriteLine($"Batch #{batch}, tickets: {String.Join(", ", tickets)} - " + (tickets.SequenceEqual(sequence) ? "OK" : "NOT FIFO!"));
        Console.WriteLine($"Performance: { perf.ElapsedMilliseconds} ms");
    }

    Console.WriteLine(Environment.NewLine + "DONE");
    Console.ReadLine();
}

结论

C#的lock语句本质是封装了Monitor.Enter和Monitor.Exit操作,它并不保证按先进先出(FIFO)的顺序授予锁。

CLR与操作系统的线程调度器没有对锁的获取顺序做强制约定,实际运行中线程获取锁的顺序会受线程优先级、系统负载、调度策略等多种因素影响。你之前观察到的“按顺序进入锁”只是偶然出现的情况,不能作为可靠的业务依赖。

你的测试代码也直接验证了这一点:当200个线程竞争同一把锁时,多数批次会输出NOT FIFO!,说明tickets列表的顺序与线程启动顺序不一致,完全打破了FIFO的预期。

如果业务场景需要严格的有序锁访问,不能依赖lock的偶然表现,建议手动基于队列+SemaphoreSlim实现有序锁,或者使用专门提供有序同步机制的组件。

内容的提问来源于stack exchange,提问作者whatever

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 14:35:23