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端支付.
一位致力于优化Windows中的锁的Windows内核开发人员告诉我有关性能的经验法则:
显然,关于锁的其他方面应该考虑:
是的,除非阅读>>>>写入,否则只支持CS。
| 归档时间: |
|
| 查看次数: |
7519 次 |
| 最近记录: |