《Windows核心编程系列》谈谈用户模式下的线程同步
作者:网络转载 发布时间:[ 2012/10/17 10:55:12 ] 推荐标签:
读写锁(RWLock)
读写锁也可以对一个资源进行保护。但是它跟关键段有所不同,读写锁允许我们区分那些想要读取资源的线程和更改资源的线程。让所有的读取资源的线程同时工作是可行的,因为读取不会破坏数据。只有当写入时才需要对写入线程进行同步。写入线程必须独占资源,它工作时无论是读取还是写入线程都必须等待。
使用读写锁之前,需要分配一个SRWLOCK结构,并调用InitializeSRWLock初始化它。
Void InitializeSRWLock(PSRWLOCK SRWLock);
初始化完成之后,写入者线程可以调用AcquireSRWLockExclusive,将SRWLock对象地址传入,获得对被保护资源的独占访问。
Void AcquireSRWLockExclusive(PSRWLOCK SRWLock);
独占访问结束后,需要调用:
Void ReleaseSRWLockExclusive(PSRWLOCK SRWLock);
解除对资源的独占。
对于读取者线程,可以通过调用:
Void AcquireSRWLockShared(PSRWLOCK SRWLock);
获得对资源的共享访问。
Void ReleaseSRWLockShared(PSRWLOCK SRWLock);
释放对资源的共享。
读写锁不能为了多次写入资源而多次锁定资源,然后再多次调用ReleaseSRWLock*来释放对资源的锁定 。
多线程会导致一些同步开销。如果使用单线程访问一个资源需要x ms,那么使用两个线程花费的时间将会>2x。因为除了同步开销外,还有多个cpu之间必须相互通信以维护高速缓存的一致性。Cpu个数越多,这种花费越多。
读写锁执行读取操作的性能要优于写入操作。这是因为两个线程可以同时读取,但是需要写入的时候只能一个一个写入。
对比各种线程同步方法,读写锁和关键段性能差不多,有些情况下读写锁甚至更优,而且还允许多个线程同时读取。因此推荐使用读写锁。使用互斥量性能是差的。这是因为等待互斥量以及后来的释放互斥量需要线程调用API,而这又会导致在用户模式和内核模式之间切换。在下一章介绍的使用内核对象进行同步时还会详细介绍。
使用读写锁也可以解决生产者-消费者问题。
如果读取者线程没有数据可读,它应该将锁释放并等待,直到生产者写入新数据为止。如果写入者将缓冲区写满,它同样应该释放锁并进入睡眠状态。要实现这样的线程同步是很复杂的,windows为我们提供一些函数简化了这些操作。
Windows提供SleepConditionVariableCS或SleepConditionVariableSRW函数,等待条件变量。线程在等待该条件变量时,会以原子方式把锁释放并将自己阻塞,直到该条件变量被触发时为止。
<SPAN style="FONT-SIZE: 18px">Bool SleepConditionVariableCS(
PCONDITION_VARIABLE pConditionVariable,
PCRITICAL_SECTION pCriticalSection,
DWORD dwMilliseconds);
Bool SleepConditionVariableSRW(
PCONDITION_VARIABLE pConditionVariable,
PSRWLOCK pSRWLock,
DWORD dwMilliseconds
ULONG Flags);</SPAN>
pConditonVariable指向一个以初始化的条件变量,调用线程将等待该条件变量。第二个参数指向一个关键段或是SRWLock对象。该关键段或SRWLock用来同步对共享资源的访问。Flags指定一旦条件变量被触发,线程将以何种方式获得锁。对读取者线程来说应该传入CONDITION_VARIABLE_LOCKMODE_SHARED表示希望共享对资源的访问。对于写入者线程应该传入0,表示独占资源。
dwMilliseconds表示我们希望线程花多少时间来等待条件被触发。在指定的时间用完时,如果条件变量尚未被触发,函数返回false,否则为true。
当另一个线程检测到相应的条件已经满足时,比如存在一个元素可以让读取者线程读取。它会调用WakeConditionVariable或WakeAllConditionVariable,触发条件变量。这样调用Sleep*函数而阻塞在该条件变量的线程会被唤醒。
<SPAN style="FONT-SIZE: 18px">Void WakeConditonVariable(
PCONDITION_VARIABLE ConditionVariable);
Void WakeAllConditionVariable(
PCONDITION_VARIABLE ConditionVariable);</SPAN>
WakeConditionVariable会使SleepConditionVariable*等待的同一个条件变量被触发的线程得到锁并返回。当此线程释放这个锁的时候,不会唤醒其他正在等待此条件变量的线程。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11