您的位置:首页 > 编程语言

window下线程同步之(Critical Sections(关键代码段、关键区域、临界区域)

2014-04-14 18:53 281 查看

关键区域(CriticalSection)

临界区是为了确保同一个代码片段在同一时间只能被一个线程访问,与原子锁不同的是临界区是多条指令的锁定,而原子锁仅仅对单条操作指令有效;临界区和原子锁只能控制同一个进程中线程的同步

使用方法:

1、初始化:InitializeCriticalSection;
2、删除:DeleteCriticalSection;
3、进入:EnterCriticalSection(可能造成阻塞);
4、尝试进入:TryEnterCriticalSection(不会造成阻塞);
5、离开:LeaveCriticalSection;


固有特点(优点+缺点):
1、是一个用户模式的对象,不是系统核心对象;
2、因为不是核心对象,所以执行速度快,有效率;
3、因为不是核心对象,所以不能跨进程使用;
4、可以多次“进入”,但必须多次“退出”;
5、最好不要同时进入或等待多个 Critical Sections,容易造成死锁;
6、无法检测到进入到 Critical Sections 里面的线程当前是否已经退出!

一般错误的情况:

#include <stdio.h>
#include <windows.h>

long g_nNum = 0 ;
DWORD WINAPI ThreadProc(__in  LPVOID lpParameter);
const int THREAD_NUM = 10;

int main()
{

HANDLE  handle[THREAD_NUM];
g_nNum = 0;
int var = 0;
while ( var< THREAD_NUM)
{
handle[ var++] = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);

}
WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);

for( var=0; var<sizeof(handle); var++)
{
CloseHandle(handle[var]);
}

return 0;
}

DWORD WINAPI ThreadProc(__in  LPVOID lpParameter)
{
Sleep(50);
g_nNum++;
Sleep(0);
printf("当前计数为:%d\n",g_nNum);
return 0;
}


运行2次结果:









用了关键区域的情况:

#include <stdio.h>
#include <windows.h>

long g_nNum = 0 ;
DWORD WINAPI ThreadProc(__in  LPVOID lpParameter);
const int THREAD_NUM = 10;

CRITICAL_SECTION g_ThreadCode;

int main()
{

HANDLE  handle[THREAD_NUM];
g_nNum = 0;
int var = 0;
InitializeCriticalSection(&g_ThreadCode);
while ( var< THREAD_NUM)
{
handle[ var++] = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
}
WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);
DeleteCriticalSection( &g_ThreadCode );

for( var=0; var<sizeof(handle); var++)
{
CloseHandle(handle[var]);
}

return 0;
}

DWORD WINAPI ThreadProc(__in  LPVOID lpParameter)
{
EnterCriticalSection( &g_ThreadCode );
g_nNum++;
printf("当前计数为:%d\n",g_nNum);
LeaveCriticalSection( &g_ThreadCode );
return 0;
}




内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: