执行原理:对于X86CPU,函数对总线发出一个硬件信号,防止另一个CPU(线程)访问同一地址(地址保护);对于A l p h aCPU,函数执行以下操作:
1) 打开C P U中的一个特殊的位标志,并注明被访问的内存地址。
2) 将内存的值读入一个寄存器。
3) 修改该寄存器。
4) 如果C P U中的特殊位标志是关闭的,则转入第二步。否则,特殊位标志仍然是打开的,
寄存器的值重新存入内存。
函数1:
//*******************************************************************//
//输入参数:Addend长变量地址(要改变的值),Value增长的长度(可以是负数)//
//****输出参数:Addend原始值******************************//
//****函数作用:实现以原子操作同步线程,使得变量递增(递减) **********//
//*******************************************************************//
long _InterlockedExchangeAdd(
long volatile * Addend,
long Value
);
__int64 _InterlockedExchangeAdd64( //64位
__int64 volatile * Addend,
__int64 Value
);
Example:
Long g_gx;
DWORD WINAPI Thread()
{
InterlockedExchangeAdd(&g_gx,1); //相当于 g_gx++ 而其他线程不可以访问g_gx
}
函数2:
//*******************************************************************//
//输入参数:Target 长变量地址(被替换的值),Value要替换的值(可以是负数)//
//****输出参数:Target 原始值******************************//
//****函数作用:实现以原子操作同步线程,使得Value替换目标变量 **********//
//*******************************************************************//
long _InterlockedExchange(
long * Target,
long Value
);
__int64 _InterlockedExchange64( //64位
__int64 * Target,
__int64 Value
);
void * _InterlockedExchangePointer( //64位
void * volatile * Target,
void * Value
);
Example:
BOOL IsUseResource = FALSE;//判断是否资源正在使用的变量
DWORD WINAPI Thread() //循环锁实现 缺点:CPU不断比较,浪费资源
{
while(InterlockedExchange(&IsUseResource,true) == true)
{
Sleep(0);//资源正在被其他线程使用,继续等待
}
//开始使用资源
InterlockedExchange(&IsUseResource,false);//资源使用完毕 释放权限
}
函数三:
//*******************************************************************//
//输入参数:Destination 长变量地址(被替换的值),Exchange 要替换的值(可以是负数)Comperand 进行比较的对象//
//****输出参数:Destination原始值******************************//
//****函数作用:实现以原子操作同步线程,实现Destination 指向的值和 Comperand 的值进行比较,若匹配,进行Exchange 替换,否则不变**********//
//*******************************************************************//
long _InterlockedCompareExchange(long volatile * Destination,long Exchange,long Comperand);注意:在线程中传递变量的地址时,变量定义不需要加“v o l a t i l e”限定词,因为即使修改,也是直接对内存地址进行操作。若在线程中传递变量的值时,变量的定义必须加 “v o l a t i l e”限定词,作用是允许除应用程序本身外的东西可以修改此值,如操作系统。
B、临界区同步
执行原理:在任何代码执行前,临界区独占某些资源的访问权,使得其他代码无权访问。
Critical_Section 声明临界区全局变量
//初始化临界区变量,并加入循环锁,
dwSpinCount
:循环次数。应用多处理器
BOOL WINAPI InitializeCriticalSectionAndSpinCount(
__out LPCRITICAL_SECTION lpCriticalSection,
__in DWORD dwSpinCount
);
//初始化临界区变量,不加入循环锁,应用于单处理器。
void WINAPI InitializeCriticalSection(
__out LPCRITICAL_SECTION lpCriticalSection
);
//释放临界区变量 (对应初始化临界区变量函数使用,成对出现)void WINAPI DeleteCriticalSection(
__inout LPCRITICAL_SECTION lpCriticalSection
);
//使用临界区保护资源,若资源正在使用,请求的线程进入等待状态。(进入内核方式)
void WINAPI EnterCriticalSection(
__inout LPCRITICAL_SECTION lpCriticalSection
);
//使用临界区保护资源,若资源正在使用,请求的线程不进入等待状态,返回true时,获得访问权。(一直在用户方式)
BOOL WINAPI TryEnterCriticalSection(
__inout LPCRITICAL_SECTION lpCriticalSection
);
//释放资源,更新资源状态 (与保护资源成对出现)
void WINAPI LeaveCriticalSection(
__inout LPCRITICAL_SECTION lpCriticalSection
);
举例说明:
CRITICAL_SECTION CriticalSection;
void main()
{
// Initialize the critical section one time only.
if (!InitializeCriticalSectionAndSpinCount(&CriticalSection,
0x80000400) )
return;
...
// Release resources used by the critical section object.
DeleteCriticalSection(&CriticalSection)
}
DWORD WINAPI ThreadProc( LPVOID lpParameter )
{
...
// Request ownership of the critical section.
EnterCriticalSection(&CriticalSection);
//
也可以是
if (TryEnterCriticalSection(&g_s))// Access the shared resource.
// Release ownership of the critical section.
LeaveCriticalSection(&CriticalSection);
...
}