<<windows核心编程>>读书笔记---第8章 用户模式下的线程同步
2013-08-23 12:35
351 查看
前言:线程的同步,经常用的到的知识。
InterLocked函数:
以原子访问的方式来增减或者减少Target变量。value为正增加的值,为负则是减少的值。
将Value的值赋给Target,并且返回Target的原来的值。
当然最强大的还有对链表的操作:
说实话这些函数我都没有用过。不过暂且做个记录吧,说不定哪天就用到了呢。
高速缓存行:其实当CUP从内存取回自己的时候,并不是取回一个字节,而是取回32位的整数倍的高速缓存行,这样,如果需要访问这个字节周围的字节,可以直接使用,大大增大了效率。如果单一的这么想确实会提高效率,可是如果是多核CPU,CPU1取出的高速缓存行,CPU2改变了该内存的值,CPU1没有得到更新,这样是很大的失误。因为CPU在设计的时候,如果有CPU改变告诉缓存行的内存,就会发送消息通知高速缓存行作废,然后重新获取高速缓存行,
所以,我们在定义结构体的时候,尽量的将只读的,只写的,不同的数据放在一起,这样会提高效率,因为改写比较大的数据可以放在同一个高速缓存行,实时进行更新,却不用动那些经常不变化的告诉缓存行。
想要获得CPU告诉缓存行的大小,可以调用GetLogicalProcessorInformation函数,该函数返回一个SYSTEM_LOGICAL_PROCESSOR_INFORMATION的结构体,该结构体的CACHE字段是一个CACHE_DESCRIPTOR结构,其中的LineSize字段表示CPU的高速缓存行的大小。(msdn中此函数有demo)
关键段和旋转锁:
定义CRITICAL_SECTION结构的变量,InitializeCriticalSection初始化该变量,把EnterCriticalSection和LeaveCriticalSection放在关键代码的首尾处,DeleteCriticalSection销毁该变量。
可惜无法在多个进程之间进行线程同步。
当一个线程拥有对资源的访问权的时候,如果另一个线程也调用EnterCritical想拥有资源,那么系统会将后者从用户状态转化为内核状态进行等待,当前者释放资源之后,系统会将后者转化为可调度状态并且更新CRITICAL_SECTION的值。不过,由于从用户状态转化为内核状态需要消耗很多的时间,很有可能在转换的时候,前者已经释放了资源。所以我们还是使用关键段+旋转锁一起使用。
当调用EnterCriticalSection的时候,他会用一个旋转锁不停的循环,尝试在一段时间内获的对该资源的访问权。只有当尝试失败的时候,线程才会切换到内核模式进入等待状态。
此函数用来初始化关键段,第一个参数为关键段的对象,第二个参数为旋转锁循环的次数。(如果为单任务处理器的话,第二个参数忽略)。参考值:保护进程堆的关键段4000
Slim读写锁:
其实Slim读写锁与上述的关键段性质类似,但是还有有所不同的:
Slim读写锁区分了读进程和写进程,因为单纯的读数据是不会破坏数据的。当写进程的时候,任何其它进程是无法共享该资源的。
首先,需要对SRWLOCK结构进行初始化
初始化完毕之后,写线程会调用AcquireSRWLockExclusive来独占共享资源。ReleaseAcquireSRWLockExclusive
读线程会调用AcquireSRWLockShared来共享资源。ReleaseSRWLockShared
对于Slim锁,也有其局限性:
1. 没有TryEnter(Shared/Exclusive)之类的函数,如果所已经被占用,那么调用AcquireSRWLockExclusive函数将会阻塞调用线程 。
2. 不可以循环嵌套使用。(有个queue的demo 以后再写,顺便当做复习)
InterLocked函数:
LONG InterlockedExchangeAdd( IN OUT PLONG Addend, IN LONG Value );
以原子访问的方式来增减或者减少Target变量。value为正增加的值,为负则是减少的值。
LONG InterlockedExchange( IN OUT PLONG Target, IN LONG Value );
将Value的值赋给Target,并且返回Target的原来的值。
当然最强大的还有对链表的操作:
说实话这些函数我都没有用过。不过暂且做个记录吧,说不定哪天就用到了呢。
高速缓存行:其实当CUP从内存取回自己的时候,并不是取回一个字节,而是取回32位的整数倍的高速缓存行,这样,如果需要访问这个字节周围的字节,可以直接使用,大大增大了效率。如果单一的这么想确实会提高效率,可是如果是多核CPU,CPU1取出的高速缓存行,CPU2改变了该内存的值,CPU1没有得到更新,这样是很大的失误。因为CPU在设计的时候,如果有CPU改变告诉缓存行的内存,就会发送消息通知高速缓存行作废,然后重新获取高速缓存行,
所以,我们在定义结构体的时候,尽量的将只读的,只写的,不同的数据放在一起,这样会提高效率,因为改写比较大的数据可以放在同一个高速缓存行,实时进行更新,却不用动那些经常不变化的告诉缓存行。
想要获得CPU告诉缓存行的大小,可以调用GetLogicalProcessorInformation函数,该函数返回一个SYSTEM_LOGICAL_PROCESSOR_INFORMATION的结构体,该结构体的CACHE字段是一个CACHE_DESCRIPTOR结构,其中的LineSize字段表示CPU的高速缓存行的大小。(msdn中此函数有demo)
关键段和旋转锁:
定义CRITICAL_SECTION结构的变量,InitializeCriticalSection初始化该变量,把EnterCriticalSection和LeaveCriticalSection放在关键代码的首尾处,DeleteCriticalSection销毁该变量。
可惜无法在多个进程之间进行线程同步。
当一个线程拥有对资源的访问权的时候,如果另一个线程也调用EnterCritical想拥有资源,那么系统会将后者从用户状态转化为内核状态进行等待,当前者释放资源之后,系统会将后者转化为可调度状态并且更新CRITICAL_SECTION的值。不过,由于从用户状态转化为内核状态需要消耗很多的时间,很有可能在转换的时候,前者已经释放了资源。所以我们还是使用关键段+旋转锁一起使用。
当调用EnterCriticalSection的时候,他会用一个旋转锁不停的循环,尝试在一段时间内获的对该资源的访问权。只有当尝试失败的时候,线程才会切换到内核模式进入等待状态。
BOOL WINAPI InitializeCriticalSectionAndSpinCount( __in_out LPCRITICAL_SECTION lpCriticalSection, __in DWORD dwSpinCount );
此函数用来初始化关键段,第一个参数为关键段的对象,第二个参数为旋转锁循环的次数。(如果为单任务处理器的话,第二个参数忽略)。参考值:保护进程堆的关键段4000
Slim读写锁:
其实Slim读写锁与上述的关键段性质类似,但是还有有所不同的:
Slim读写锁区分了读进程和写进程,因为单纯的读数据是不会破坏数据的。当写进程的时候,任何其它进程是无法共享该资源的。
首先,需要对SRWLOCK结构进行初始化
VOID WINAPI InitializeSRWLock( __out PSRWLOCK SRWLock );
初始化完毕之后,写线程会调用AcquireSRWLockExclusive来独占共享资源。ReleaseAcquireSRWLockExclusive
读线程会调用AcquireSRWLockShared来共享资源。ReleaseSRWLockShared
对于Slim锁,也有其局限性:
1. 没有TryEnter(Shared/Exclusive)之类的函数,如果所已经被占用,那么调用AcquireSRWLockExclusive函数将会阻塞调用线程 。
2. 不可以循环嵌套使用。(有个queue的demo 以后再写,顺便当做复习)
相关文章推荐
- <<windows核心编程>>读书笔记---第9章 内核对象进行线程同步
- <<windows核心编程>>读书笔记---第6章 线程基础
- <<C++ Qt设计模式>>读书笔记一:第七章 库与设计模式
- 《Windows核心编程 5th》读书笔记---第8章 用户模式下的线程同步
- <<Android源码设计模式解析与实战>>读书笔记----- Android NDK开发学习
- <<windows核心编程>>读书笔记---第4章 进程
- <<cocoa设计模式>>
- <<操作系统精髓与设计原理>>读书笔记(一) 并发性:互斥与同步(1)
- <<鸟哥的私房菜>>--读书笔记--HFS
- <<高级语言程序设计>>读书笔记
- <<什么是数学>> 读书笔记 第一章
- <<一线架构师实践指南>>读书笔记之二----PA阶段
- 第8章 用户模式下的线程同步(1)_Interlocked系列函数
- <<C++网络编程 卷1 运用ACE和模式消除复杂性>>
- 《Effective C#》读书笔记——条目25:用事件模式实现通知<使用C#表达设计>
- Windows Via C/C++ 读书笔记 5 用户模式的线程同步
- <<Information Storage and Management>>读书笔记 之四
- <<读书笔记>>系列--Once And Only Once
- 单用户模式<修改root密码>
- <<iText in Action 2nd>>4.1节(Constructing tables)读书笔记