为什么超薄读写器独占锁定优于共享?

Jic*_*hao 7 windows multithreading

我使用Windows Via C/C++中的代码测试了Windows 7下的超薄读写器锁的性能.

结果令我惊讶的是,共享锁定性能.这是代码和结果.

unsigned int __stdcall slim_reader_writer_exclusive(void *arg)
{
    //SRWLOCK srwLock;
    //InitializeSRWLock(&srwLock);

    for (int i = 0; i < 1000000; ++i) {
        AcquireSRWLockExclusive(&srwLock);
        g_value = 0;
        ReleaseSRWLockExclusive(&srwLock);
    }
    _endthreadex(0);
    return 0;
}

unsigned int __stdcall slim_reader_writer_shared(void *arg)
{

    int b;
    for (int i = 0; i < 1000000; ++i) {
        AcquireSRWLockShared(&srwLock);
        //b = g_value;
        g_value = 0;
        ReleaseSRWLockShared(&srwLock);
    }
    _endthreadex(0);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

g_value 是一个全局int volatile变量.

在此输入图像描述

你能解释一下为什么会这样吗?

小智 20

对于小型通用锁(如SRWLocks,它只是一个指针大小),这是一个非常常见的结果.

关键点:如果你有一个非常小的保护代码部分,这样锁本身的开销可能占主导地位,那么使用独占锁比共享锁更好.

此外,Raymond Chen关于g_Value争论的论点也是正确的.如果在两种情况下都读取了g_Value而不是写入,那么您可能会注意到共享锁的好处.

细节:

SRW锁使用单个指针大小的原子变量实现,该变量可以采用多种不同的状态,具体取决于低位的值.这些位的使用方式的描述超出了这个注释的范围 - 状态转换的数量非常高 - 所以,我只提到您在测试中可能遇到的几个状态.

初始锁定状态:(0,ControlBits:0) - SRW锁定以所有位设置为0开始.

共享状态:(ShareCount:n,ControlBits:1) - 当没有冲突的独占获取并且锁保持共享时,共享计数直接存储在锁变量中.

独占状态:(ShareCount:0,ControlBits:1) - 当没有冲突的共享获取或独占获取时,锁具有低位设置而没有别的.

示例争用状态:(WaitPtr:ptr,ControlBits:3) - 当发生冲突时,等待锁的线程使用在等待线程堆栈上分配的数据形成队列.lock变量存储指向队列尾部的指针而不是共享计数.

在此方案中,当您不知道初始状态时尝试获取独占锁是对锁定字的单次写入,设置低位并检索旧值(这可以在x86上使用LOCK BTS指令完成).如果您成功(正如您在1线程情况下所做的那样),您可以进入锁定区域而无需进一步操作.

尝试获取共享锁是一个更复杂的操作:您需要首先读取锁变量的初始值以确定旧的共享计数,增加您读取的共享计数,然后使用LOCK CMPXCHG有条件地写回更新的值指令.这是一个明显更长的串行相关指令链,因此速度较慢.CMPXCGH在许多处理器上比LOCK BTS等无条件原子指令慢一点.

理论上可以通过假设锁在开始时处于其初始状态并首先执行LOCK CMPXCHG来加速锁的第一次共享获取.这将加速锁的初始共享获取(所有这些都在您的单线程情况下),但它会显着减慢锁已经共享并发生第二次共享获取的情况.

在释放锁时会发生类似的一组不同操作,因此管理共享状态的额外成本也会在ReleaseSRWLockShared端支付.


sam*_*sft 5

一位致力于优化Windows中的锁的Windows内核开发人员告诉我有关性能的经验法则:

  1. 在大多数情况下,请使用关键部分以获得最佳性能
  2. 如果您阅读与写作至少4:1,请考虑使用SRW锁
  3. 仅当您的代码绝对不允许饥饿时才使用互斥锁

显然,关于锁的其他方面应该考虑:

  1. 您必须清理CS,而不必清理SRW锁
  2. CS锁可以递归获取,而SRW锁不能递归获取
  3. 互斥锁可以同步UM和KM,如果您处于KM,则CS和SRW锁不是真正的选择

是的,除非阅读>>>>写入,否则只支持CS。