临界区的互斥控制
临界区:简述
临界区是一种轻量级机制,在某一时间内只允许一个线程执行某个给定代码段。通常在修改全局数据(如集合类)时会使用临界区。事件、多用户终端执行程序和信号量也用于多线程同步,但临界区与它们不同,它并不总是执行向内核模式的控制转换,这一转换成本昂贵。稍后将会看到,要获得一个未占用临界区,事实上只需要对内存做出很少的修改,其速度非常快。只有在尝试获得已占用临界区时,它才会跳至内核模式。这一轻量级特性的缺点在于临界区只能用于对同一进程内的线程进行同步。
临界区由 WINNT.H 中所定义的 RTL_CRITICAL_SECTION 结构表示。因为您的 C++ 代码通常声明一个 CRITICAL_SECTION 类型的变量,所以您可能对此并不了解。研究 WINBASE.H 后您会发现:
class=codeSampletypedef RTL_CRITICAL_SECTION CRITICAL_SECTION;
建立线程函数
CreateThread
(
LPSECURITY_ATTRIBUTES lpThreadAttributes, //安全指针,可以为NULL,但该handle
不被继承
SIZE_T dwStackSize, // 线程栈大小,若为0表示使用默认值
LPTHREAD_START_ROUTINE lpStartAddress, // 指向线程函数的指针
LPVOID lpParameter, // 传递给线程函数的参数,可以保存一个指针值
DWORD dwCreationFlags, // 线程建立时的初始标记,运行或挂起
LPDWORD lpThreadId // 指向接收线程号的DWORD变量
);
临界资源控制函数
1)事件对象的创建
事件对象的作用是为线程传送一个公共的事件信号。
HANDLE CreateEvent
(
LPSECURITY_ATTRIBUTES lpEventAttributes, // 安全属性结构指针,可为NULL
BOOL bManualReset, // 手动清除信号标记,TRUE在WaitForSingleObject后必须手动调 ,用RetEvent清除信号。若为FALSE则在WaitForSingleObject后,系统自动清除事件信号
BOOL bInitialState, // 初始状态,TRUE有信号,FALSE无信号
LPCTSTR lpName // 信号量的名称
);
2)互斥量的创建
互斥量的作用是保证每次只能有一个线程获得互斥量而得以继续执行。
"HANDLE CreateMutex
(
LPSECURITY_ATTRIBUTES lpMutexAttributes, // 安全属性结构指针,可为NULL
BOOL bInitialOwner, // 当前建立互斥量是否占有该互斥量 。TRUE表示占有,这样其他线程就不能获得此互斥量也就无法进入由 。该互斥量控制的临界区。FALSE表示不占有该互斥量
LPCTSTR lpName // 信号量的名称
);
临界区信号的初始化
void InitializeCriticalSection
(
LPCRITICAL_SECTION lpCriticalSection // 临界区变量指针
);
4)阻塞函数
如果等待的信号量不可用,那么线程就会挂起,直到信号可用线程才会被唤醒,该函数会自动修改信号,如Event,线程被唤醒之后Event信号会变得无信号,Mutex、Semaphore等也会变。
DWORD WaitForSingleObject
(
HANDLE hHandle, // 等待对象的句柄
DWORD dwMilliseconds // 等待毫秒数,INFINITE表示无限等待
);