Windows几种线程同步方法介绍
作者:网络转载 发布时间:[ 2013/2/7 9:42:34 ] 推荐标签:
高级线程同步。刚刚简单的说了一下旋转锁,现在又来说旋转锁的坏,旋转锁的问题在于等待的线程一直在执行毫无用处的该死的死循环,浪费CPU的时间,这肯定是不能容忍的,虽然曾经一度容忍过它。当一个线程需要某个资源,而这个资源被另一个线程占用时,如果这个线程等了一会儿还不能获得这个资源,那么这个线程应该被切换到等待状态,让系统充当该线程的代理,当该资源可以被使用时,系统会将该线程唤醒,然后该线程可以独占该资源。而实现这一功能的是关键段。
关键段。关键段是一小段代码,在执行之前需要独占对一些共享资源的访问,这种方式可以让多行代码以原子的方式进行访问,当有一个线程对访问这段代码时其他线程只能等待。使用关键段的步骤如下:
CRITICAL_SECTION g_cs;//构造一个CRITICAL_SECTION实例
InitializeCriticalSection(&g_cs);//初始化g_cs的成员
EnterCriticalSection(&g_cs);//进入关键段
LeaveCriticalSection(&g_cs);//离开关键段
DeleteCriticalSection(&g_cs);//清理g_cs
EnterCriticalSection会检查结构CRITICAL_SECTION的成员变量,这些成员表示是否有线程正在访问资源,以及哪个线程正在访问资源,EnterCriticalSection会进行一些测试。如果没有线程正在访问资源,EnterCriticalSection会更新变量成员,以表示已经有线程正在访问资源,并马上从EnterCriticalSection返回,继续执行关键段中的代码,如果变量成员表示已经有线程正在访问资源,那么EnterCriticalSection会使用一个事件内核对象把线程切换成等待状态,等待状态的线程是不会浪费CPU的时间的,系统会记住这个线程想要使用这个资源,一旦当前线程调用LeaveCriticalSection,系统会自动更新CRITICAL_SECTION的成员变量,并将等待的线程切换成可调度状态。
LeaveCriticalSection会检查结构CRITICAL_SECTION的成员变量并将计数器减一,如果计数器变为0,LeaveCriticalSection会更新成员变量表示现在没有线程访问资源,若有等待的线程,则将等待的线程切换成可调度的状态。
当一个线程进入关键段时,若有线程正在访问关键段,那么系统会将新的线程切换成等待状态,这意味着将线程从用户模式切换成内核模式,这个切换的开销大约是1000个CPU周期,这个开销其实是很大的,所以在EnterCriticalSection内部使用旋转锁,并不是马上将线程切换成等待状态,而是先用旋转锁试探一些,看线程是否释放了对资源的访问,如果释放了,新的线程不用被切换成等待状态了,可以直接访问资源了,也是说花了旋转锁轮询的时间,如果旋转锁轮询了一段时间,线程还是没有释放资源,对不起系统不会让它继续轮询了,因为系统也不知道还要轮询多久,毕竟轮询一直都是在消耗CPU的时间,系统会停止轮询,将新的线程切换成等待状态,当前一个资源释放对资源的访问,系统会将新的线程切换成可调度状态。
Silm读/写锁。SRWLock的目的和关键段是一样的,是对资源的保护,不让其他线程访问。不同的是,它区分线程是读线程还是写线程。我们都是知道,一个资源可以同时被多个线程同时读,是不能同时读,或是读写。也是是说写必须是独占的方式,而读可以以共享的方式访问。
读写锁调用的函数如下,跟关键段差不多,我不废话了。
RTL_SRWLOCK lock;
InitializeSRWLock(&lock);
AcquireSRWLockExclusive(&lock);//独占的方式访问
ReleaseSRWLockExclusive(&lock);
AcquireSRWLockShared(&lock);//共享的方式访问
ReleaseSRWLockShared(&lock);
相关推荐
更新发布
功能测试和接口测试的区别
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