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

简介:

    临界区(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里初始化临界区

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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 ;



然后观察线程的回调函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
DWORD  WINAPI ThrCalcProc1( LPVOID  lp)
{
//获得结构体指针
PPARAMS param2 =  static_cast <PPARAMS>(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;
}



wKioL1l3GQzx8VVWAABBdQiuVwk894.png-wh_50




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






 本文转自超级极客51CTO博客,原文链接:http://blog.51cto.com/12158490/1950907,如需转载请自行联系原作者


相关文章
|
安全
VC++关于使用WaitForSingleObject等待线程安全退出,出现死机问题的解决
VC++关于使用WaitForSingleObject等待线程安全退出,出现死机问题的解决
487 0
|
程序员 API 数据库
|
C++ Windows 机器学习/深度学习
VC++ 线程同步(转)
http://www.cnblogs.com/kzloser/archive/2013/01/09/2852385.html
512 0
|
1天前
|
存储 Java C++
【C++类和对象】探索static成员、友元以及内部类
【C++类和对象】探索static成员、友元以及内部类
|
1天前
|
安全 程序员 编译器
【C++类和对象】初始化列表与隐式类型转换
【C++类和对象】初始化列表与隐式类型转换