您的位置:首页 > 其它

复习笔记之二--用户方式线程同步

2013-12-26 09:47 246 查看
A、原子访问:互锁函数家族
执行原理:对于X86CPU,函数对总线发出一个硬件信号,防止另一个CPU(线程)访问同一地址(地址保护);对于AlphaCPU,函数执行以下操作:

1)打开CPU中的一个特殊的位标志,并注明被访问的内存地址。

2)将内存的值读入一个寄存器。

3)修改该寄存器。

4)如果CPU中的特殊位标志是关闭的,则转入第二步。否则,特殊位标志仍然是打开的,

寄存器的值重新存入内存。

函数1:

//*******************************************************************//

//输入参数:Addend长变量地址(要改变的值),Value增长的长度(可以是负数)//

//****输出参数:Addend原始值******************************//

//****函数作用:实现以原子操作同步线程,使得变量递增(递减)**********//

//*******************************************************************//

long_InterlockedExchangeAdd(

longvolatile*Addend,

longValue

);

__int64_InterlockedExchangeAdd64(//64位

__int64volatile*Addend,

__int64Value

);

Example:

Longg_gx;

DWORDWINAPIThread()

{

InterlockedExchangeAdd(&g_gx,1);//相当于g_gx++而其他线程不可以访问g_gx

}

函数2:

//*******************************************************************//

//输入参数:Target长变量地址(被替换的值),Value要替换的值(可以是负数)//

//****输出参数:Target原始值******************************//

//****函数作用:实现以原子操作同步线程,使得Value替换目标变量**********//

//*******************************************************************//

long_InterlockedExchange(

long*Target,

longValue

);

__int64_InterlockedExchange64(//64位

__int64*Target,

__int64Value

);

void*_InterlockedExchangePointer(//64位

void*volatile*Target,

void*Value

);

Example:
BOOLIsUseResource=FALSE;//判断是否资源正在使用的变量
DWORDWINAPIThread()//循环锁实现缺点:CPU不断比较,浪费资源
{
while(InterlockedExchange(&IsUseResource,true)==true)
{
Sleep(0);//资源正在被其他线程使用,继续等待
}
//开始使用资源
InterlockedExchange(&IsUseResource,false);//资源使用完毕释放权限
}
函数三:
//*******************************************************************//
//输入参数:Destination长变量地址(被替换的值),Exchange要替换的值(可以是负数)Comperand进行比较的对象//
//****输出参数:Destination原始值******************************//
//****函数作用:实现以原子操作同步线程,实现Destination指向的值和Comperand的值进行比较,若匹配,进行Exchange替换,否则不变**********//
//*******************************************************************//
[code]long_InterlockedCompareExchange(
longvolatile*Destination,
longExchange,
longComperand
);
注意:在线程中传递变量的地址时,变量定义不需要加“volatile”限定词,因为即使修改,也是直接对内存地址进行操作。若在线程中传递变量的值时,变量的定义必须加“volatile”限定词,作用是允许除应用程序本身外的东西可以修改此值,如操作系统。
B、临界区同步
执行原理:在任何代码执行前,临界区独占某些资源的访问权,使得其他代码无权访问。
Critical_Section声明临界区全局变量
//初始化临界区变量,并加入循环锁,
dwSpinCount
:循环次数。应用多处理器

BOOLWINAPIInitializeCriticalSectionAndSpinCount(
__outLPCRITICAL_SECTIONlpCriticalSection,
__inDWORDdwSpinCount
);
//初始化临界区变量,不加入循环锁,应用于单处理器。
voidWINAPIInitializeCriticalSection(
__outLPCRITICAL_SECTIONlpCriticalSection
);
//释放临界区变量(对应初始化临界区变量函数使用,成对出现)
voidWINAPIDeleteCriticalSection(
__inoutLPCRITICAL_SECTIONlpCriticalSection
);
//使用临界区保护资源,若资源正在使用,请求的线程进入等待状态。(进入内核方式)
[code]voidWINAPIEnterCriticalSection(
__inoutLPCRITICAL_SECTIONlpCriticalSection
);
//使用临界区保护资源,若资源正在使用,请求的线程不进入等待状态,返回true时,获得访问权。(一直在用户方式)
BOOLWINAPITryEnterCriticalSection(
__inoutLPCRITICAL_SECTIONlpCriticalSection
);
//释放资源,更新资源状态(与保护资源成对出现)
voidWINAPILeaveCriticalSection(
__inoutLPCRITICAL_SECTIONlpCriticalSection
);
举例说明:

CRITICAL_SECTIONCriticalSection;
voidmain()
{
//Initializethecriticalsectiononetimeonly.
if(!InitializeCriticalSectionAndSpinCount(&CriticalSection,
0x80000400))
return;
...
//Releaseresourcesusedbythecriticalsectionobject.
DeleteCriticalSection(&CriticalSection)
}
DWORDWINAPIThreadProc(LPVOIDlpParameter)
{
...
//Requestownershipofthecriticalsection.
EnterCriticalSection(&CriticalSection);
//
也可以是
if(TryEnterCriticalSection(&g_s))
//Accessthesharedresource.
//Releaseownershipofthecriticalsection.
LeaveCriticalSection(&CriticalSection);
...
}
[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: