关键段(主要是用户模式下的线程同步,但是竞争激烈的情况下会进入内核态)
一般是EnterCriticalSection和LeaveCriticalScetion配对使用,需要先创建一个CRITICAL_SECTION结构。
下面的函数用来进行初始化
void InitializerCriticalSection(PCRITICAL_SECTION pcs);
当线程不在需要访问共享资源的时候,应该调用下面的函数来清理结构
void deleteCriticalSection(PCRITICAL_SECTION pcs);
TryEnterCriticalSection从来不会让调用线程进入等待状态,他会通过返回值来表示调用线程是否获准访问资源,因此如果TryEnterCriticalSection发现资源正在被其他线程访问,那么它会返回false。每一个返回true的TryEnterCriticalSection调用必须有一个对应的LeaveCriticalSection。
互斥量
要使用互斥量,进程必须先调用CreateMutexl来插件创建一个互斥量
HANDLE CreateMutex( PSECURITY_ATTRIBUTES psa, BOOL bInitialOwner, PCTSTR pszName);bInitialOwner用来控制互斥量的初始状态。如果传入false,那么表示互斥量不属于任何线程。
线程ID和递归计数都为0。此时互斥量处于触发状态。如果为true,互斥量的线程ID将被设为主调线程的线程ID,递归计数被设为1。
OpenMutex来打开一个已存在的互斥量。
HANDLE OpenMutex( DWORD dwDesiredAccess, BOOL bInheritHandle, PCTSTR pszName);使用WaitForSingleObject和ReleaseMutex配合使用,不需要的时候调用closehandle来释放该句柄
信号量
与其他所有内核对象相同,它们也包含一个使用计数,但是它们还包括另外两个32bit值,一个最大资源计数和一个当前资源计数。最大资源计数表示信号量可以控制的最大资源数量,当前资源计数表示信号量当前可用资源的数量。
信号量的规则如下:
1.如果当前资源计数大于0,那么信号量处于触发状态
2.如果当前资源计数等于0,那么信号量处于未触发状态
3.系统绝对不会让当前资源计数变为负数
4.当前资源计数绝对不会大于最大资源计数
创建信号量内核对象:
HANDLE CreateSomaphore( PSECURITY_ATTRIBUTE psa, LONG lInitialCount, LONG lMaximuCount, PCTSTR pszName); lMaximumCount告诉系统应用程序能够处理的资源最大数量。 lInitialCount表示这些资源一开始有多少可供使用。任何进程都可以调用OpenSemaphore来得到一个已经存在的信号量的句柄
HANDLE OpenSemaphore( DWORD dwDesiredAccess, BOOL hInheritHandle, PCTSTR pszName); 线程通过调用ReleaseSemaphore来递增信号量的当前资源计数。 // 信号量对象句柄 HANDLE hSemaphore; UINT ThreadProc15(LPVOID pParam) { // 试图进入信号量关口 WaitForSingleObject(hSemaphore, INFINITE); // 线程任务处理 AfxMessageBox("线程一正在执行!"); // 释放信号量计数 ReleaseSemaphore(hSemaphore, 1, NULL); return 0; } UINT ThreadProc16(LPVOID pParam) { // 试图进入信号量关口 WaitForSingleObject(hSemaphore, INFINITE); // 线程任务处理 AfxMessageBox("线程二正在执行!"); // 释放信号量计数 ReleaseSemaphore(hSemaphore, 1, NULL); return 0; } UINT ThreadProc17(LPVOID pParam) { // 试图进入信号量关口 WaitForSingleObject(hSemaphore, INFINITE); // 线程任务处理 AfxMessageBox("线程三正在执行!"); // 释放信号量计数 ReleaseSemaphore(hSemaphore, 1, NULL); return 0; } …… void CSample08View::OnSemaphore() { // 创建信号量对象 hSemaphore = CreateSemaphore(NULL, 2, 2, NULL); // 开启线程 AfxBeginThread(ThreadProc15, NULL); AfxBeginThread(ThreadProc16, NULL); AfxBeginThread(ThreadProc17, NULL); }