推荐参考博客:秒杀多线程第五篇 经典线程同步 关键段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);
}

 

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

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

 

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

windows多线程同步--临界区的更多相关文章

  1. 总结windows多线程同步互斥

    windows多线程同步互斥--总结 我的windows多线程系列文章: windows多线程--原子操作 windows多线程同步--事件 windows多线程同步--互斥量 windows多线程同 ...

  2. windows多线程同步互斥--总结

    我的windows多线程系列文章: windows多线程--原子操作 windows多线程同步--事件 windows多线程同步--互斥量 windows多线程同步--临界区 windows多线程同步 ...

  3. windows多线程同步

    概述 任何单个应用程序都不能完全使该处理器达到满负荷.当一个线程遇到较长等待时间事件时,同步多线程还允许另一线程中的指令使用所有执行单元.例如,当一个线程发生高速缓存不命中,另一个线程可以继续执行.同 ...

  4. Windows多线程同步系列之二-----关键区

    关键区对象为:CRITICAL_SECTION 当某个线程进入关键区之后,其他线程将阻塞等待,知道该线程释放关键区的拥有权. 关键区同步主要有以下几个API 初始化关键区对象,无返回值,传入一个关键区 ...

  5. Windows多线程同步系列之一-----互斥对象

    多线程同步之互斥对象 作者:vpoet mail:vpoet_sir@163.com   对卖票问题进行线程间同步,本文将在上文的基础上,使用互斥对象对线程进行同步. 首先看看windows API ...

  6. windows多线程同步总结

    1.多线程同步与多线程互斥的关系 其实这也是我一直困扰的问题,在这里我只是说说我的理解.我的理解是多线程互斥是针对于多线程资源而言的. 而多线程同步是针对于多线程时序问题.由于线程的并发性导致其运行时 ...

  7. windows多线程同步--事件

    推荐参考博客:秒杀多线程第六篇 经典线程同步 事件Event   事件是内核对象,多用于线程间通信,可以跨进程同步 事件主要用到三个函数:CreateEvent,OpenEvent,SetEvent, ...

  8. windows多线程同步--互斥量

    关于互斥量的基本概念:百度百科互斥量 推荐参考博客:秒杀多线程第七篇 经典线程同步 互斥量Mutex 注意:互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似, ...

  9. windows多线程同步--信号量

    推荐参考博客:秒杀多线程第八篇 经典线程同步 信号量Semaphore   首先先介绍和windows信号量有关的两个API:创建信号量.释放信号量   HANDLE WINAPI CreateSem ...

随机推荐

  1. poj3481 splaytree模板题

    找不到错在哪里,先留着吧 /* splay是以键值排序的! 三个操作:1 a b,z增加键值为b的点,值为a 2,查询最大值 3,查询最小值 需要的操作:rotate,splay,insert,fin ...

  2. 性能测试三十六:内存溢出和JVM常见参数及JVM参数调优

    堆内存溢出: 此种溢出,加内存只能缓解问题,不能根除问题,需优化代码堆内存中存在大量对象,这些对象都有被引用,当所有对象占用空间达到堆内存的最大值,就会出现内存溢出OutOfMemory:Java h ...

  3. DOMContentLoaded与load的区别

    声明:此文章为转载(点击查看原文),如有侵权24小时内删除.联系QQ:1522025433. (1)在chrome浏览器的开发过程中,我们会看到network面板中有这两个数值,分别对应网 络请求上的 ...

  4. 如何批量的在django中对url进行用户登陆限制

    参考URL: https://blog.csdn.net/hanshengzhao/article/details/79540306?utm_source=blogxgwz0 1,首先定义一个内部有装 ...

  5. 038 关于HIVE的配置

    一:常用版本 1.版本 0.13.1 2014年 1.2.1   2015年 版本之间的区别:支持SQL不同,向关系型数据库靠拢. 目前看到的版本是2.3.2了. 2.官网 二:安装配置hive 1. ...

  6. python套接字编程基础

    python套接字编程 目录 socket是什么 套接字的工作流程 基于tcp的套接字 基于udp的套接字 socket是什么 客户端/服务器架构(C/S架构) 服务端:提供服务的一端 客户端:请求服 ...

  7. Java—集合框架详解

    一.描述Java集合框架 集合,在Java语言中,将一系类的对象看成一个整体. 首先查看jdk中的Collection类的源码后会发现Collection是一个接口类,其继承了java迭代接口Iter ...

  8. Java中递归和循环的优劣

    介绍: 你用你手中的钥匙打开一扇门,结果去发现前方还有一扇门,紧接着你又用钥匙打开了这扇门,然后你又看到一扇门......但是当你开到一扇门时,发现前方是一堵墙无路可走了,你选择原路返回--这就是递归 ...

  9. 如何成为java高手

    成为Java高手是每个Java学习者的梦想,但目前Java知识分支众多,我们该如何学习?本文介绍成为Java高手需要注意的25个学习目标,希望对正在成为Java高手的您有所帮助. 1.你需要精通面向对 ...

  10. 在web.xml中配置Spring的application.xml

    <context-param> <!-- 请记住这里的名称不能够乱写,必须一模一样,区分大小写 java类去启动项目 contextClass--> <param-nam ...