关键段(主要是用户模式下的线程同步,但是竞争激烈的情况下会进入内核态)
一般是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(lMaximumCount告诉系统应用程序能够处理的资源最大数量。
PSECURITY_ATTRIBUTE psa,
LONG lInitialCount,
LONG lMaximuCount,
PCTSTR pszName);
lInitialCount表示这些资源一开始有多少可供使用。
任何进程都可以调用OpenSemaphore来得到一个已经存在的信号量的句柄
HANDLE OpenSemaphore(线程通过调用ReleaseSemaphore来递增信号量的当前资源计数。
DWORD dwDesiredAccess,
BOOL hInheritHandle,
PCTSTR pszName);
// 信号量对象句柄
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);
}