1) 关键代码段(临界区)工作在用户方式下。
2) 关键代码段(临界区)是指一个小代码段,在代码能够执行前,它必须独占对某些资源的访问权。
用InitializeCriticalSection来初始化临界区,最后用DeleteCriticalSection来释放临界区资源。
在线程中用EnterCriticalSection和LeaveCriticalSection来分别进入和离开临界区。
三种实现同步方法即使用互斥对象、事件对象与关键代码段的比较
1) 互斥对象和事件对象属于内核对象,利用内核对象进行线程同步,速度较慢,但利用互斥对象和事件对象这样的内核对象,可以在多个进程中的各个线程间进行同步。
2) 关键代码段是工作在用户方式下,同步速度较快,但在使用关键代码段时,很容易进入死锁状态,因为在等待进入关键代码段时无法设定超时值。
下面为使用关键代码段来模拟简单多线程售卖火车票的例子:
#include <windows.h>
#include <iostream.h>
int tickets=100;
CRITICAL_SECTION cs;
DWORD WINAPI Proc1Fun(LPVOID lpParameter);
DWORD WINAPI Proc2Fun(LPVOID lpParameter);
main()
{
HANDLE hthread1;
HANDLE hthread2;
hthread1=CreateThread(NULL,0,Proc1Fun,NULL,0,NULL);
hthread2=CreateThread(NULL,0,Proc2Fun,NULL,0,NULL);
InitializeCriticalSection(&cs);
CloseHandle(hthread1);
CloseHandle(hthread2);
Sleep(4000);
DeleteCriticalSection(&cs);
return 0;
}
DWORD WINAPI Proc1Fun(LPVOID lpParameter)
{
while(TRUE)
{
EnterCriticalSection(&cs);
if(tickets>0)
{
Sleep(1);
cout<<"Thread1 sells ticket"<<tickets--<<endl;
}
else
break;
LeaveCriticalSection(&cs);
}
return 0;
}
DWORD WINAPI Proc2Fun(LPVOID lpParameter)
{
while(TRUE)
{
EnterCriticalSection(&cs);
if(tickets>0)
{
Sleep(1);
cout<<"Thread2 sells ticket"<<tickets--<<endl;
}
else
break;
LeaveCriticalSection(&cs);
}
return 0;
}