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

A、 原子访问:互锁函数家族

执行原理:对于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);
    ...
}

你可能感兴趣的:(thread,线程,操作系统,对象,处理器)