通常会导致执行几个C P U 周期(通常小于5 0 ),并且不会从用户方式转换为内核方式(通常这
需要执行1 0 0 0个C P U周期)。
当然,可以使用I n t e r l o c k e d E x c h a n g e A d d减去一个值
—
只要为第二个参数传递一个负值。
I n t e r l o c k e d E x c h a n g e A d d将返回在* p l A d d e n d中的原始值。
下面是另外两个互锁函数:
I n t e r l o c k e d E x c h a n g e和I n t e r l o c k e d E x c h a n g e P o i n t e r 能够以原子操作方式用第二个参数中传
递的值来取代第一个参数中传递的当前值。如果是 3 2位应用程序,两个函数都能用另一个3 2位
值取代一个3 2位值。但是,如果是个6 4位应用程序,那么I n t e r l o c k e d E x c h a n g e能够取代一个3 2
位值,而I n t e r l o c k e d E x c h a n g e P o i n t e r则取代6 4位值。两个函数都返回原始值。当实现一个循环
锁时,I n t e r l o c k e d E x c h a n g e是非常有用的:
w h i l e循环是循环运行的,它将g _ f R e s o u r c e I n U s e中的值改为T R U E,并查看它的前一个值,
以了解它是否是T R U E。如果这个值原先是FA L S E,那么该资源并没有在使用,而是调用线程
将它设置为在用状态并退出该循环。如果前一个值是 T R U E,那么资源正在被另一个线程使用,
w h i l e循环将继续循环运行。
如果另一个线程要执行类似的代码,它将在 w h i l e循环中运行,直到g _ f R e s o u r c e I n U s e 重新
改为FA L S E。调用函数结尾处的 I n t e r l o c k e d E x c h a n g e ,可显示应该如何将g _ f R e s o u r c e I n U s e重
新设置为FA L S E。
当使用这个方法时必须格外小心,因为循环锁会浪费 C P U时间。C P U 必须不断地比较两个
值,直到一个值由于另一个线程而“奇妙地”改变为止。另外,该代码假定使用循环锁的所有
线程都以相同的优先级等级运行。也可以把执行循环锁的线程的优先级提高功能禁用(通过调
用S e t P r o c e s s P r i o r i t y B o o s t或s e t T h r e a d P r i o r i t y B o o s t函数来实现之)。
此外,应该保证将循环锁变量和循环锁保护的数据维护在不同的高速缓存行中(本章后面
部分介绍)。如果循环锁变量与数据共享相同的高速缓存行,那么使用该资源的 C P U 将与试图
访问该资源的任何C P U 争用高速缓存行。
第 8章 用户方式中线程的同步计计175