Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows 为什么slim读写器独占锁的性能优于共享锁?_Windows_Multithreading - Fatal编程技术网

Windows 为什么slim读写器独占锁的性能优于共享锁?

Windows 为什么slim读写器独占锁的性能优于共享锁?,windows,multithreading,Windows,Multithreading,我已经通过C/C++测试了Windows7下slim读写器锁的性能 结果让我惊讶的是,独占锁定性能比共享锁定性能好。下面是代码和结果 unsigned int __stdcall slim_reader_writer_exclusive(void *arg) { //SRWLOCK srwLock; //InitializeSRWLock(&srwLock); for (int i = 0; i < 1000000; ++i) { Acqu

我已经通过C/C++测试了Windows7下slim读写器锁的性能

结果让我惊讶的是,独占锁定性能比共享锁定性能好。下面是代码和结果

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;
}
unsigned int\uu stdcall slim\u reader\u writer\u exclusive(void*arg)
{
//SRWLOCK-SRWLOCK;
//初始化srwLock(&srwLock);
对于(int i=0;i<1000000;++i){
AcquireSRWLockExclusive(&srwLock);
g_值=0;
ReleaseSRWLockExclusive(&srwLock);
}
_endthreadex(0);
返回0;
}
未签名整数\uu stdcall slim\u读写器\u共享(void*arg)
{
int b;
对于(int i=0;i<1000000;++i){
获取SRWLockShared(&srwLock);
//b=g_值;
g_值=0;
释放srwlockshared(&srwLock);
}
_endthreadex(0);
返回0;
}
g_值
是一个全局int可变变量

你能解释一下为什么会发生这种情况吗

猜测:


独占锁是更简单的情况。共享锁支持并行性,但需要处理饥饿的可能性,因此会产生额外的开销。

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

密钥提取:如果您有一个非常小的受保护代码段,因此锁本身的开销可能占主导地位,那么使用独占锁比使用共享锁更好

此外,陈雷蒙关于g_值争论的论点也是正确的。如果在这两种情况下都读取而不是写入g_值,您可能会注意到共享锁的好处

详细信息:

SRW锁是使用一个指针大小的原子变量实现的,该变量可以根据低位的值呈现多种不同的状态。关于这些位的使用方式的描述超出了本评论的范围——状态转换的数量相当高——因此,我将仅提及您在测试中可能遇到的几个状态

初始锁定状态:(0,控制位:0)--SRW锁定从所有位设置为0开始

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

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

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

在这个方案中,当您不知道初始状态是对锁字的单次写入时,尝试获取独占锁,以设置低位并检索旧值(这可以在x86上通过lock BTS指令完成)。如果成功(在1线程的情况下总是这样),则可以继续进入锁定区域,无需进一步操作

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

理论上,通过假设锁在开始时处于初始状态并首先执行锁CMPXCHG,可以加速锁的第一次共享获取。这将加快锁的初始共享获取(所有这些都在单线程情况下),但它将大大降低锁已被共享且发生第二次共享获取的情况


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

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

  • 在大多数情况下使用关键部分以获得最佳性能
  • 如果读写比至少为4:1,请考虑SRW锁
  • 只有在代码绝对不允许饥饿时才使用互斥锁
  • 显然,锁还有其他方面需要考虑:

  • 您必须清理CS,而不必清理SRW锁
  • CS锁可以递归获取,而SRW锁不能
  • 互斥锁可以同步UM和KM,如果您在KM中,CS和SRW锁实际上不是一个选项

  • 所以是的,除非读>>>>写,否则最好使用CS。

    你测试了多少个线程实例?@djna:结果显示,我已经测试了1,2,4个线程。在一个线程的情况下,
    42ms
    50ms
    之间的差异对我来说似乎是一个合理的抖动-增加样本数量以获得更精确的结果詹德沃夏克:对不起,我找不到你。您的意思是互斥锁1的结果是错误的吗?共享锁在
    g_值上有争用。独占锁不存在。由于锁不公平,独占版本允许一个线程运行多次迭代(始终保留
    g_值的所有权)。共享版本强制
    g_值
    的所有权在核心之间不断反弹。