为什么 lock 比 ReaderWriterLockSlim 快 240%?

Why lock is 240% faster than ReaderWriterLockSlim?

我读了另一个 SO 问题:When is ReaderWriterLockSlim better than a simple lock?

而且它并不能准确解释为什么 ReaderWriterLockSlimlock 慢。

我的测试是肯定的 - 零争用测试,但仍然无法解释惊人的差异。

读锁耗时2.7s,写锁2.2s,加锁1.0s

这是完整的代码:

using System;
using System.Diagnostics;
using System.Threading;

namespace test
{
    internal class Program
    {
        static int[] data = new int[100000000];
        static object lock1 = new object();
        static ReaderWriterLockSlim lock2 = new ReaderWriterLockSlim();

        static void Main(string[] args)
        {
            for (int z = 0; z < 3; z++)
            {
                var sw = Stopwatch.StartNew();

                for (int i = 0; i < data.Length; i++)
                {
                    lock (lock1)
                    {
                        data[i] = i;
                    }
                }

                sw.Stop();

                Console.WriteLine("Lock: {0}", sw.Elapsed);

                sw.Restart();

                for (int i = 0; i < data.Length; i++)
                {
                    try
                    {
                        lock2.EnterReadLock();
                        data[i] = i;
                    }
                    finally
                    {
                        lock2.ExitReadLock();
                    }
                }

                sw.Stop();

                Console.WriteLine("Read: {0}", sw.Elapsed);

                sw.Restart();

                for (int i = 0; i < data.Length; i++)
                {
                    try
                    {
                        lock2.EnterWriteLock();
                        data[i] = i;
                    }
                    finally
                    {
                        lock2.ExitWriteLock();
                    }
                }

                sw.Stop();

                Console.WriteLine("Write: {0}\n", sw.Elapsed);

            }

            Console.ReadKey(false);
        }
    }
}

您正在查看两个设备。左边是一个lock. At the right is a ReaderWriterLockSlim.

左边的设备用于从一个位置控制单个电动装置 lamp。右边的设备用于从两个不同的位置控制两个 lamp。¹ 左边的设备购买更便宜,需要的接线更少,安装和操作更简单,并且能量损失更少由于热量比右边的设备。

与 SPST/DPDT electric switches 的类比可能远非完美,但我的观点是 lock 是一种比 ReaderWriterLockSlim 相对简单的机制。它用于对同质工作线程组实施单一策略。另一方面,ReaderWriterLockSlim 用于对两个不同的工作组(读者和作者)执行两种不同的策略,关于他们如何与同一组和另一组的成员交互。毫不奇怪,更复杂的机制比更简单的机制具有更高的运营成本(开销)。这是为了更好地控制工作线程而必须付出的代价。

¹ 也许不是。我不是电工!

感谢@canton 和@KevinGosse - 我发现 @HansPassant 完美地回答了我 2013 年的问题:When exactly does .NET Monitor go to kernel-mode?

所以锁在 no-contention 场景中更快只是因为它有更轻的逻辑并且不涉及内核模式。