windows核心编程-关键段与SRWLock
来源:互联网 发布:手机直播网络要求 编辑:程序博客网 时间:2024/05/19 02:44
线程同步的方式主要有:临界区、互斥区、事件、信号量四种方式。
临界区线程同步也叫关键段线程同步
一、关键段
关键段(Critical Section)是一小段代码,它在执行之前需要独占一些共享资源的访问权。这里的原子方式是代码除了
当前线程之外,没有其他任何线程会同时访问该资源。当然系统仍然可以暂停当前线程去调度其他线程。但是在当
前线程离开关键段之前,系统是不会去调度任何想要访问统一资源的其他线程的。
在使用关键段(CRITICAL_SECTION)时,只有两个必要条件:
1、想要访问资源的线程必须知道用来保护资源的CRITICAL_SECTION对象地址。
CRITICAL_SECTION对象可以作为全局对象来分配,也可以作为局部对象来分配,
或者从堆中动态地分配。
2、如何线程在试图访问被保护的资源之前,必须对CRITICAL_SECTION结构的内部
成员进行初始化。
- const int COUNT=10000;
- int g_nSum = 0;
- CRITICAL_SECTION g_cs;
- DWORD WINAPI FirstThread(PVOID pvParam)
- {
- EnterCriticalSection(&g_cs);
- g_nSum = 0;
- for (int n = 0; n < COUNT; ++n)
- {
- g_nSum += n;
- }
- LeaveCriticalSection(&g_cs);
- return g_nSum;
- }
- DWORD WINAPI SecondThread(PVOID pvParam)
- {
- EnterCriticalSection(&g_cs);
- g_nSum = 0;
- for (int n = 0; n < COUNT; ++n)
- {
- g_nSum += n;
- }
- LeaveCriticalSection(&g_cs);
- return g_nSum;
- }
EnterCriticalSection和LeaveCriticalSection之间。两个函数传入的是g_nSum的地址
关键段:
优点:容易使用,而且在内部也使用了Interlocked函数,所以执行速度很快。
缺点:无法用来在多个进程之间对线程进行同步 哭库玛
关键段线程同步常用函数介绍
- //1、首先我们要分配一个CRITICAL_SECTION对象,并进行初始化(使用关键段同步的线程必须调用此函数)
- void InitializeCriticalSection( LPCRITICAL_SECTION lpCriticalSection )
- //2、当知道线程将不再需要访问共享资源时,我们应该调用下边的函数来清理CRITICAL_SECTION结构
- void DeleteCriticalSection( LPCRITICAL_SECTION lpCriticalSection )
- //3、在对保护的资源进行访问之前,必须调用下面的函数
- void EnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection )
- //可以对上边的函数多次调用,表示调用线程被获准访问的次数
- //4、也可以用下边的函数代替EnterCriticalSection
- BOOL TryEnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection )
- //通过返回值判断当前线程是否获准访问资源,线程永远不会进入等待状态,如果
- //返回TRUE表示该线程获准并正在访问资源,离开时必须调用LeaveCriticalSection()
- //5、在代码完成对资源的访问后,必须调用以下函数,释放访问权限
- void LeaveCriticalSection( LPCRITICAL_SECTION lpCriticalSection )
- //转载请注明文章来自:http://blog.csdn.net/windows_nt
以上访问方式(EnterCriticalSection方式)可能会使调用线程切换到等待状态,这意味着线程必须从用户模式切换到内核模式,这个切换开销非常大。为了提高关键段的性能,Microsoft把旋转锁合并到了关键段中。因此,当调用EnterCriticalSection的时候,它会用一个旋转锁不断地循环,尝试在一段时间内获得对资源的访问权,只有当尝试失败时,线程才会切换到内核模式并进入等待状态。
(如何传入dwSpinCount的值,使效果最佳:通过不断的尝试,一般为4000,参考值)
//1、为了在使用关键段的时候同时使用旋转锁,我们必须调用下面的函数来初始化关键段 BOOL InitializeCriticalSectionAndSpinCount( LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount )
//第一个参数是关键段结构的地址 //第二个参数dwSpinCount表示我们希望旋转锁循环的次数。 //2、我们也可以调用下面的函数来改变关键段的旋转次数 DWORD SetCriticalSectionSpinCount( LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount ) //如果主机只有一个处理器,函数会忽略dwSpinCount参数
SRWLock允许我们区分那些想要读取资源的值的线程(读取者线程)和想要更新资源的值的线程(写入者线程)
//1、首先我们要分配一个SRWLOCK对象并用下边函数初始化它。 void InitializeSRWLock( __out PSRWLOCK SRWLock ) //2、请求对保护资源的独占访问权(写权限) void AcquireSRWLockExclusive( __inout PSRWLOCK SRWLock ) //3、完成对资源的更新后,应该解除对资源的锁定 void ReleaseSRWLockExclusive( __inout PSRWLOCK SRWLock ) //4、对应的读者线程函数如下 void AcquireSRWLockShared( __inout PSRWLOCK SRWLock ) void ReleaseSRWLockShared( __inout PSRWLOCK SRWLock )与关键段相比,PSRWLock缺乏下面两个特性
1、不存在TryEnter(Share/Exclusive)SRWLock之类的函数,如果锁已经被占用,呢么调用会阻塞调用线程
2、不能递归获得PSRWLOCK.也就是说,一个线程不能为了多次写入二多次锁定资源,然后再多次
调用ReleaseSRWLock *释放对资源的锁定
推荐使用SRWLock来代替关键段:性能更优,不仅快,而且允许多个线程同时读取,对那些只需要读取共享资源的
线程来说,提高了吞吐量和可伸缩性。
volatile读取 -->volatile写入-->Interlocked API(原子方式)-->SRWLock-->关键段-->内核对象
- windows核心编程-关键段与SRWLock
- windows核心编程-关键段(临界区)线程同步
- 《windows核心编程》读后编码--关键段
- Win32核心编程 读书笔记四 关键代码段与互斥对象
- Windows核心编程笔记(八)用户模式下的线程同步 SRWLock剖析
- windows核心编程之关键代码
- 【Windows核心编程学习笔记】用户模式下的线程同步之二---关键段(critical section)
- Windows关键段
- windows critical section (关键段)
- 关键段与旋转锁
- 字符与字符串 [windows核心编程]
- Windows核心编程--Unicode与ANSI
- windows核心编程---错误报告与应用程序恢复
- 白话windows多线程同步之关键段
- Windows多线程(三) 关键段 CS
- 多线程编程之一:关键段的使用
- 【Windows 核心编程】Windows 核心编程 -- 进程
- 【Windows核心编程】Windows核心编程 -- 作业
- 互联网数据中心——IDC(Internet Data Center)
- shell 脚本学习
- sql查询优化
- 分布式跟踪系统—Zipkin
- 如何保存ie8的设置
- windows核心编程-关键段与SRWLock
- 查看远程git仓库的信息
- 苦逼程序员的求职之路
- 网站左侧导航代码如何编写
- powercenter问题
- c#多维数组的建立及操作 总结
- Maven web project & TST工具体验
- 安卓应用,实现3DES加密
- c语言:n*n矩阵最大值与其位置