先来复习两个简单的英语单词吧:
critical : 临界的;关键的
section: 区域;区段
所以critical section可以翻译为临界区,也可以翻译为关键代码段,我个人倾向于前者。
会拉屎的人,一定会利用临界区来实现线程同步。
下面,我将介绍利用临界区来实现线程同步。什么是临界区呢?临界区好比一个厕所的槽位,有人在里面,你就不能进入。我发现,每天早上八九点种的时候,厕所的每一个槽位基本都是满的,想拉屎,总是要等,哎,临界区的设计真是太有生活哲理了,还是那句话:大道至简,Everything should be made as simple as possible.
还是售票系统,依然是直接上代码:
#include <windows.h>
#include <iostream.h>
DWORD WINAPI Fun1Proc(LPVOID lpParameter);
DWORD WINAPI Fun2Proc(LPVOID lpParameter);
int tickets = 100;
CRITICAL_SECTION g_cs;
int main()
{
HANDLE hThread1;
HANDLE hThread2;
hThread1 = CreateThread(NULL, 0, Fun1Proc, NULL, 0, NULL);
hThread2 = CreateThread(NULL, 0, Fun2Proc, NULL, 0, NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);
// 初始化临界区
InitializeCriticalSection(&g_cs);
Sleep(4000);
// 销毁临界区
DeleteCriticalSection(&g_cs);
return 0;
}
DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
while(1)
{
// 等待调用线程获得临界区所有权(类似于WaitForSingleObject)
EnterCriticalSection(&g_cs);
if(tickets > 0)
{
Sleep(1);
cout << "thread1 sell ticket : " << tickets-- << endl;
LeaveCriticalSection(&g_cs); // 离开临界区(类似于释放互斥对象)
}
else
{
break;
}
}
return 0;
}
DWORD WINAPI Fun2Proc(LPVOID lpParameter)
{
while(1)
{
// 等待调用线程获得临界区所有权(类似于WaitForSingleObject)
EnterCriticalSection(&g_cs);
if(tickets > 0)
{
Sleep(1);
cout << "thread2 sell ticket : " << tickets-- << endl;
LeaveCriticalSection(&g_cs); // 离开临界区(类似于释放互斥对象)
}
else
{
break;
}
}
return 0;
}
|