热门IT资讯网

VC++线程同步(三) 临界区使用例子

发表于:2024-11-26 作者:热门IT资讯网编辑
编辑最后更新 2024年11月26日,临界区(Crtical Section)同步对象用户模式下的同步对象Win32中,最容易使用的一个同步机制就是(关键段)Critical Section, 某些共享资源具有互斥性,也就是它要求被互斥地

临界区(Crtical Section)同步对象


用户模式下的同步对象

Win32中,最容易使用的一个同步机制就是(关键段)Critical Section, 某些共享资源具有互斥性,也就是它要求被互斥地使用,他也是用于资源的互斥, 在大部分情况下,使用临界区替换Mutex(Mutex是内核模式下的同步对象)。

局限性:他只能用于同步单个进程中的线程。


在任何同步机制当中,无论是哪个操作系统下,都不要

长时间的锁住资源,如果一直锁定资源,就会一致阻止其他线程的执行,

使整个程序,处于完全停止的状态。

不要在critical section中调用Sleep或任何Wait等待之类的api函数.

、、、 临界区很容器造成资源死锁.



相关Api函数



1初始化一个临界区

InitializeCriticalSection函数

VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection //critical section);

lpCriticalSection 临界资源对象指针





2释放一个临界区对象来释放所有的资源,使得不再拥有这个对象

void DeleteCriticalSection(

LPCRITICAL_SECTION lpCriticalSection

)

lpCriticalSection 指向一个不再需要的CRITICAL_SECTION变量





3 进入临界区,也就意味着我进行加锁,在他之后已经加锁了

void EnterCriticalSection(

LPCRITICAL_SECTION lpCriticalSection

)

lpCriticalSection 临界区资源对象指针





4 离开临界区 ,也就意味着解锁,所有的资源都处于安全状态

void LeaveCriticalSection(

LPCRITICAL_SECTION lpCriticalSection

)

lpCriticalSection 临界区资源对象指针





临界区和Mutex的区别


临界区是用户模式下的,优点是速度快,缺点是容易线程死锁。他

不能跨进程,而Mutex内核模式下的同步对象是可以进行,安全的跨进程操作,但是他相对与用户模式,速度比较慢, 因此正常情况下,使用

临界区。


临界区 Mutex

1 速度: 快 慢

2 跨进程: 不可以 可以

3 声明: CRITICAL_SECTION cs HANDLE hmtx;

4 初始化: InitializeCriticalSection(&cs) hmtx = CreateMutex(NULL,FALSE,NULL);

5 清理: CloseHandle DeleteCriticalSection

6 无限的等待:EnterCriticalSection(&cs) WaitForSingleObject(,INFINITE).

7 不等待(不阻塞)TryEnterCriticalSection(&cs) WaitForSingleObject(,0);

8 任意时间 临界区是没有这个功能 WaitForSingleObject(,1000)

9 释放(解锁)LeaveCriticalSection(&cs)

ReleaseMutex(.);





临界区使用实例


首先定义一个全局的CRITICAL_SECTION g_cs;

在Create里初始化临界区

case WM_CREATE:{int cyChar = HIWORD(GetDialogBaseUnits());thrParams2.hwnd = hWnd;thrParams2.cyChar = cyChar;//初始化临界区InitializeCriticalSection(&g_cs);//创建线程HANDLE handleTicket1 = CreateThread(NULL, 0, ThrCalcProc1, &thrParams2, 0, NULL);HANDLE handleTicket2 = CreateThread(NULL, 0, ThrCalcPro2, &thrParams2, 0, NULL);//关闭线程句柄CloseHandle(handleTicket1);CloseHandle(handleTicket2);}case WM_PAINT:hdc = BeginPaint(hWnd, &ps);// TODO:  在此添加任意绘图代码...TextOut(hdc, clientCX / 4, 0, _T("使用临界区实现同步"), lstrlen(_T("使用临界区实现同步")));EndPaint(hWnd, &ps);break;case WM_DESTROY://清理临界区的指针内存DeleteCriticalSection(&g_cs);PostQuitMessage(0);break;



然后观察线程的回调函数

DWORD WINAPI ThrCalcProc1(LPVOID lp){//获得结构体指针PPARAMS param2 = static_cast(lp);//生成随机数种子srand(time(NULL));TCHAR szBuf[50] = { 0 };HDC hdc;while (true){//休眠一秒  不要在进入临界区 休眠Sleep(1000);//进入临界区 (加锁)EnterCriticalSection(&g_cs);//g_subjectNum是数字题的数量if (g_subjectNum > 0){//检查文本是否超出窗口显示范围,如果是就刷新窗口,并重新设置iLine值//g_iLine2 = CheckTextRange(param2->hwnd, param2->cyChar, param2->cyChar,g_iLine2);//随机产生两个数int lval = rand() % 100;int rval = rand() % 100;int res = lval + rval;//把解锁 绘制到窗口上wsprintf(szBuf, _T("线程1第%d题:%d + %d = %d"),g_subjectNum--,lval,rval,res);hdc = GetDC(param2->hwnd);TextOut(hdc, 0, g_iLine2*param2->cyChar,szBuf, lstrlen(szBuf));ReleaseDC(param2->hwnd,hdc);g_iLine2++;//解锁LeaveCriticalSection(&g_cs);}else{ //解锁LeaveCriticalSection(&g_cs);break;}}return 0;}







代码下载地址:http://down.51cto.com/data/2329647







0