一 windows下的方法
1 原子访问系列函数(优点是相对于其他的方案, 执行效率高)
(1)原子加减法
LONG __cdecl InterlockedExchangeAdd(LONG volatile*Addend,LONG Value);
LONGLONG __cdecl InterlockedExchangeAdd64(LONGLONG volatile*Addend,LONGLONG Value);
分别针对32位/64位有符号整数进行原子加法的操作, 当Value为负数时, 做原子减法,返回初始值
(2) 原子替换
LONG __cdecl InterlockedExchange(LONG volatile *Target,LONG Value);//32位
SHORT __cdecl InterlockedExchange16(SHORT volatile *Target,SHORT Value);//16位
LONG LONG __cdecl InterlockedExchange64(LONG LONG volatile *Target,LONGLONG Value);//64位
PVOID __cdecl InterlockedExchangePointer(PVOID volatile *Target,PVOID Value); //这个本意是用来替换指针变量的, 其实也可以用来替换普通的变量, 此时PVOID可以理解成VOID
把第一个参数的指向的值替换为第二个参数, 并返回替换之前的值, 其中最后一个是自适应的函数, 在32位系统下替换32位值, 64位替换64位值, 返回的是替换之前的值
(3)原子比较替换
LONG __cdecl InterlockedCompareExchange(LONG volatile *Destination, LONG Exchange,LONG Comparand);
LONGLONG __cdecl InterlockedCompareExchange64(LONGLONG volatile *Destination, LONGLONG Exchange,LONGLONG Comparand);
PVOID __cdecl InterlockedCompareExchangePointer(PVOID volatile *Destination, PVOID Exchange,PVOID Comparand);
先比较再替换, 如果不同则不替换
2 使用关键段(优点: 内部会使用1中的函数, 运行效率比较高; 缺点: 不能跨进程使用)
(1)初始化函数
CRITICAL_SECTION cs;
void __stdcall InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
BOOL WINAPI InitializeCriticalSectionAndSpinCount(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount);
两个的区别是第二个在使用关键段的同时也使用自旋锁, 当某个要进入临界区的线程被判定为需要等待时, 先使用自旋锁方式进行等待, 然后再进入等待状态.
使用场景是如果等待的时间比较短, 这种效率会更高,因为使线程进入等待状态需要使用大约1000个cpu周期. 第二个参数一般设置为4000以下
(2)进入离开临界区
void WINAPI EnterCriticalSection(_Inout_ LPCRITICAL_SECTION lpCriticalSection);
void WINAPI LeaveCriticalSection(_Inout_ LPCRITICAL_SECTION lpCriticalSection);
(3)删除结构体
void WINAPI DeleteCriticalSection(_Inout_ LPCRITICAL_SECTION lpCriticalSection);