首页 技术 正文
技术 2022年11月14日
0 收藏 542 点赞 3,016 浏览 2822 个字

推荐参考博客:秒杀多线程第五篇 经典线程同步 关键段CS

 

关于临界区的观念,一般操作系统书上面都有。

适用范围:它只能同步一个进程中的线程,不能跨进程同步。一般用它来做单个进程内的代码快同步,效率比较高

windows中与临界区有关的结构是 CRITICAL_SECTION,关于该结构体的内部结构可参考here

使用时,主线程中要先初始化临界区,最后要删除临界区,具体使用见下面代码:

                                                                              本文地址

从一个例子来说明:假设有三个线程都需要使用打印机,我们可以把打印的代码放到临界区,这样就可以保证每次只有一个线程在使用打印机。

 

 #include<string>
#include<iostream>
#include<process.h>
#include<windows.h>
using namespace std; //定义一个临界区
CRITICAL_SECTION g_cs;//线程绑定的函数返回值和参数是确定的,而且一定要__stdcall
unsigned __stdcall threadFun(void *param)
{
EnterCriticalSection(&g_cs);//进入临界区,如果有其他线程则等待
cout<<*(string *)(param)<<endl;
LeaveCriticalSection(&g_cs);//退出临界区,其他线程可以进来了
return 1;
}int main()
{
//初始化临界区
InitializeCriticalSection(&g_cs); HANDLE hth1, hth2, hth3;
string s1 = "first", s2 = "second", s3 = "third"; //创建线程
hth1 = (HANDLE)_beginthreadex(NULL, 0, threadFun, &s1, 0, NULL);
hth2 = (HANDLE)_beginthreadex(NULL, 0, threadFun, &s2, 0, NULL);
hth3 = (HANDLE)_beginthreadex(NULL, 0, threadFun, &s3, 0, NULL); //等待子线程结束
WaitForSingleObject(hth1, INFINITE);
WaitForSingleObject(hth2, INFINITE);
WaitForSingleObject(hth3, INFINITE); //一定要记得关闭线程句柄
CloseHandle(hth1);
CloseHandle(hth2);
CloseHandle(hth3); //删除临界区
DeleteCriticalSection(&g_cs);
}

 

再看另外一个问题:编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推, 仿照文章windows多线程同步–信号量中的代码,我们把信号量替换成临界区。

 #include<string>
#include<iostream>
#include<process.h>
#include<windows.h>
using namespace std;
//声明3个临界区
CRITICAL_SECTION g_cs1, g_cs2, g_cs3;//线程绑定的函数返回值和参数是确定的,而且一定要__stdcall
unsigned __stdcall threadFunA(void *)
{
for(int i = 0; i < 10; i++){
EnterCriticalSection(&g_cs1);//进入临界区
cout<<"A";
LeaveCriticalSection(&g_cs2);//离开临界区
}
return 1;
}
unsigned __stdcall threadFunB(void *)
{
for(int i = 0; i < 10; i++){
EnterCriticalSection(&g_cs2);//进入临界区
cout<<"B";
LeaveCriticalSection(&g_cs3);//离开临界区
}
return 2;
}
unsigned __stdcall threadFunC(void *)
{
for(int i = 0; i < 10; i++){
EnterCriticalSection(&g_cs3);//进入临界区
cout<<"C";
LeaveCriticalSection(&g_cs1);//离开临界区
}
return 3;
}int main()
{
//初始化临界区
InitializeCriticalSection(&g_cs1);
InitializeCriticalSection(&g_cs2);
InitializeCriticalSection(&g_cs3); HANDLE hth1, hth2, hth3; //创建线程
hth1 = (HANDLE)_beginthreadex(NULL, 0, threadFunA, NULL, 0, NULL);
hth2 = (HANDLE)_beginthreadex(NULL, 0, threadFunB, NULL, 0, NULL);
hth3 = (HANDLE)_beginthreadex(NULL, 0, threadFunC, NULL, 0, NULL); //等待子线程结束
WaitForSingleObject(hth1, INFINITE);
WaitForSingleObject(hth2, INFINITE);
WaitForSingleObject(hth3, INFINITE); //一定要记得关闭线程句柄
CloseHandle(hth1);
CloseHandle(hth2);
CloseHandle(hth3); //删除临界区
DeleteCriticalSection(&g_cs1);
DeleteCriticalSection(&g_cs2);
DeleteCriticalSection(&g_cs3);
}

 

windows多线程同步–临界区

为什么会这样呢,因为临界区有所有权的概念,即某个线程进入临界区后,就拥有该临界区的所有权,在他离开临界区之前,他可以无限次的再次进入该临界区,上例中线程A获得临界区1的所有权后,在线程C调用LeaveCriticalSection(&g_cs1)之前,A是可以无限次的进入临界区1的。利用信号量之所以可以实现题目的要求,是因为信号量没有所有权的概念,某个线程获得信号量后,如果信号量的值为0,那么他一定要等到信号量被释放时,才能再次获得

关于临界区的详细解释清参考秒杀多线程第五篇 经典线程同步 关键段CS

 

【版权声明】转载请注明出处http://www.cnblogs.com/TenosDoIt/p/3601308.html

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,083
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,558
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,407
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,180
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,817
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,900