Interlocked系列函数
Interlocked函数是以原子方式访问资源,保证同一时刻只有一个线程访问它,常用于多线程编程。
因为从汇编的角度看,哪怕很简单的一条高级语言都可以被编译成多条机器指令。在多线程环境下,这条语句的执行就可能被打断。而在打断期间,其中间结果可能己经被其他线程更改过,从而导致错误的结果。
有一个很经典的面试题:
现在有一个进程中存在一个全局变量a,初值为0。两个线程同时对变量a执行a++操作,通过循环各累加1000次,最终a的值会是多少?
答案是不确定,a++的过程在汇编层面有三步,
- 先从内存中取出a的值,放到寄存器中,
- 对其进行递增操作
- 把寄存器的值赋给内存
线程切换的时候,不知道会在哪一步,所以不确定。
如果对a用的是InterlockedIncrement(a),结果就很明了了!
Interlocked系列函数总结
Name | DataValue | Function |
---|---|---|
InterlockedAdd | LONG | 原子加法操作,返回操作结果 |
InterlockedIncrement(Decrement) | LONG | 原子递增/减操作,返回操作结果 |
InterlockedIncrement(Decrement)64 | LONG64 | |
InterlockedIncrement(Decrement)16 | SHORT | |
InterlockedAnd(Or/Xor) | LONG | 原子与/或/异或操作,返回第一参数操作前的值 |
InterlockedAnd(Or/Xor)64 | LONG64 | |
InterlockedAnd(Or/Xor)16 | SHORT | |
InterlockedAnd(Or/Xor)8 | CHAR | |
InterlockedExchangeAdd | LONG | 原子加法操作,返回第一参数操作前的值 |
InterlockedExchangeAdd64 | LONG64 | |
InterlockedExchange | LONG | 原子赋值操作,把第二参数的值赋给第一参数,返回第一参数操作前的值 |
InterlockedExchange64 | LONG64 | |
InterlockedExchange16 | SHORT | |
InterlockedExchange8 | CHAR | |
InterlockedExchangePointer | PVOID | |
InterlockedCompareExchange | LONG | 原子比较和交换操作,比较第一和第三参数的值,如果相等则将第二参数的值赋给第一参数,否则不执行任何操作,返回第一参数操作前的值 |
InterlockedCompareExchange64 | LONG64 | |
InterlockedCompareExchange16 | SHORT | |
InterlockedCompareExchangePointer | PVOID |
部分函数原型如下:
LONG InterlockedAdd(
LONG volatile *Addend,
LONG Value
);
LONG InterlockedIncrement(
LONG volatile *Addend
);
LONG InterlockedAnd(
LONG volatile *Destination,
LONG Value
);
LONG InterlockedExchangeAdd(
LONG volatile *Addend,
LONG Value
);
LONG InterlockedExchange(
LONG volatile *Target,
LONG Value
);
LONG InterlockedCompareExchange(
LONG volatile *Destination,
LONG ExChange,
LONG Comperand
);