Windows几种线程同步方法介绍
作者:网络转载 发布时间:[ 2013/2/7 9:42:34 ] 推荐标签:
系统中的所有线程都要访问系统资源,一个线程霸占某个资源,其他需要该资源的线程不能完成自己的任务;另外如一个线程在读取某块内存中的数据,而另一个线程又正在修改这块内存的值,这同样不是我们想要的,所以线程之间必须要有一套自己的规则,不然凌乱了。线程之间需要通信,如A线程霸占某个B线程需要的资源X,在A占用期间,B线程只能等待,或处于挂起状态,当A线程用完资源X后,系统会告诉线程B,资源X可以用了,或是将处于挂起状态的线程B唤醒,然后线程B获得对资源X的控制权,其他想用资源X的线程得经历B刚才的遭遇。当多个线程同时需要某个资源时必须遵守下面两个规则:
1、多个线程“同时”访问资源,不能破坏资源的完整性。
2、一个线程需要通知其他线程某项任务已经完成。
原子访问:Interlocked系列函数。多线程编程大部分情况与原子访问有关,即一个线程在访问某个资源时,确保没有其他线程能访问该资源。
增量函数InterlockedExchangeAdd结构如下:
InterlockedExchangeAdd(
unsigned long volatile *Addend,//被增量变量的地址
unsigned long Value//增量值
)
Volatile表示每次都成内存中读取数据,而不会从高速缓存中读取数据,如一个全局变量,在一个多线程函数中被修改,在多核CPU中,这个变量可能在多个CPU的高速缓存中都有副本,如果不用volatile修饰,那么可能会因为优化的原因,CPU不会读内存中的数据,而是直接从高速缓存中读取数据,在这种情况下,很可能这个值已经被修改了,这样CPU读取到的不是新的数据,程序肯定会出错,用volatile修饰后,这个变量的所有高速缓存会失效,不会出现这种问题。在多线程编程中volatile作用非常大,效率也高。但他是只能修饰单个变量,不能修饰代码段。
InterlockedExchangeAdd执行的速度是非常快的,只需要占用几个CPU周期。用InterlockedExchangeAdd来修改某个变量的值,好像有点大材小用了,因为用Volatile足够了,简单迅速。但在实现旋转锁时InterlockedExchange非常有用。旋转锁的代码大致如下:
bool sourceIsUse=false;
void fun()
{
//一直等待直到资源可用
while(InterlockedExchange(&sourceIsUse,true)==true)
{
Sleep(0);
}
//访问资源的操作
......
//资源用好了,打开锁,让其他等待的资源访问
InterlockedExchange(&sourceIsUse,false);
}
InterlockedExchange:将第一个参数的值修改成第二个参数的值,返回第一个参数原来的值。在第一个线程来的时候,它顺利的闯过了While循环,并上了锁,导致while始终为true,后来的线程一直在while里面打转,当前面的线程用完之后,他会把锁打开,然后新来的线程可以跳出while循环,并上锁(在等待时一直在上锁),开锁独占资源了,新来的线程又开始等待。像大厦前门的旋转门,一拨人进去之后,后面的人只能在外面等,等里面的人出去之后,后面的人也可以进去了,周而复始。
高速缓存行。当CPU从内存中读取一个字节时,它并不是真的只读一个字节,而是读取一个高速缓存行,一个高速缓存行可能是32个字节、64个字节或是128个字节,它始终读取的字节数是32的整数倍,这样CPU不用非常频繁的读取内存,从而提高程序的性能,当CPU访问某块内存是它会访问这块内存旁边的内存的概率是非常大的,于是一起读了。更多关于数据对齐的信息请看我的文章《数据对齐》。
相关推荐
更新发布
功能测试和接口测试的区别
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