VC++并发编程中,原子操作是很常用的技术,现将常用API做一下介绍:
VC++原子操作MSDN路径: https://docs.microsoft.com/zh-cn/windows/win32/api/winnt/
常用原子操作API:
一. 增减操作
(1) LONG InterlockedIncrement(IN OUT LONG volatile *lpAddend);
lpAddend为长整型变量的地址,返回值为+1后的值。这个函数的主要作用是原子性自增(相当于++操作)。
(2) LONG InterlockedDecrement(IN OUT LONG volatile *lpAddend);
lpAddend为长整型变量的地址,返回值为-1后的值。这个函数的主要作用是原子性自减(相当于--操作)。
(3) LONG InterlockedExchangeAdd( LPLONG Addend, LONG Increment );
Addend为长整型变量的地址,Increment为想要在Addend指向的长整型变量上增加的数值(可以是负数)。这个函数的主要作用是保证这个加操作为一个原子访问。
二. 交换操作
(1) LONG InterlockedExchange( LPLONG Target, LONG Value );
(2) PVOID InterlockedExchangePointer( PVOID *Target, PVOID Value );
用第二个参数的值取代第一个参数指向的值。函数返回值为原始值。
三. 比较交换操作
(1) LONG InterlockedCompareExchange(
LPLONG Destination, LONG Exchange, LONG Comperand );
(2) PVOID InterlockedCompareExchangePointer(
PVOID *Destination, PVOID Exchange, PVOID Comperand );
如果第三个参数与第一个参数指向的值相同,那么用第二个参数取代第一个参数指向的值。函数返回值为原始值。
API测试代码:
#include <Winnt.h>
void TestAtom()
{
static volatile long s_state = 0;
//不比较直接交换:修改s_state为1,并返回s_state的原始值
InterlockedExchange(&s_state, 1); //可以被 ExInterlockedExchangeUlong取代
cout << "1 " << s_state << endl; // 1
//比较再交换:第1个参数与第3个参数比较,如果相等,用第2个参数替换第一个参数
InterlockedCompareExchange(&s_state, 2, 0);
cout << "2 " << s_state << endl; // 1
InterlockedExchange(&s_state, 0);
cout << "3 " << s_state << endl; // 0
InterlockedCompareExchange(&s_state, 100, 0);
cout << "4 " << s_state << endl; // 100
//原子加1操作
InterlockedIncrement(&s_state);
cout << "5 " << s_state << endl; // 101
//原子减1操作
InterlockedDecrement(&s_state);
cout << "6 " << s_state << endl; // 100
//原子加n(n可以是负数)操作:修改s_state值加10,并返回s_state的原始值
InterlockedExchangeAdd(&s_state, 10);
cout << "7 " << s_state << endl; // 110
}
代码运行效果如下: