线程同步CriticalSection
孙鑫 第十五/十六课之四 线程同步CriticalSection
说明
在使用多线程时,一般很少有多个线程完全独立的工作。往往是多个线程同时操作一个全局变量来获取程序的运行结果。多个线程同时访问同一个全局变量,如果都是读取操作,则不会出现问题。如果是写操作,则会发生错误。这时候,我们可以通过临界区,为全局变量设置一个保护,保证同时只有一个线程可以访问此变量,其他变量进入等待状态。
临界区(Critical Section)是一段独占对某些共享资源访问的代码,在任意时刻只允许一个线程对共享资源进行访问。如果有多个线程试图同时访问临界区,那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操作共享资源的目的。
临界区,类似互斥对象Mutex,用起来比较简单,速度快,是比较推荐的一种。
一般步骤:
初始化一个临界区(新建一个电话亭,只能容纳一个人)
等待进入临界区(等待进入电话亭,进入后上锁别人继续等待,如果多次上锁则要多次开锁)
离开临界区(离开电话亭要开锁,以便让其他人进入,有几道锁开几道锁,如果不开锁则别人不能进入)
删除临界区(城管把电话亭拆了)
1 初始化
VOID InitializeCriticalSection(
LPCRITICAL_SECTION lpCriticalSection //[out] CRITICAL_SECTION结构体指针,实际是struct _RTL_CRITICAL_SECTION类型。
);
初始化一个临界区,相当于新建一个电话亭。
eg.
CRITICAL_SECTION criticalSection;
InitializeCriticalSection(&criticalSection);
2 进入临界区
VOID EnterCriticalSection(
LPCRITICAL_SECTION lpCriticalSection // [in / out]
);
eg.
EnterCriticalSection(&criticalSection); //进入临界区,加锁,如果多次加锁则要有多次开锁
3 离开临界区
VOID LeaveCriticalSection(
LPCRITICAL_SECTION lpCriticalSection // [in / out]
);
eg.
LeaveCriticalSection(&criticalSection); //离开临界区,开锁,有几道锁开几道锁
4 删除临界区
VOID DeleteCriticalSection(
LPCRITICAL_SECTION lpCriticalSection // [in / out]
);
删除临界区,前提是临界区必须已经用InitializeCriticalSection函数创建
eg.
DeleteCriticalSection(&criticalSection);
5 实例
两个子线程分别给两个编辑框赋值,用临界区保证他们不同时更新
/////////////////////////////////////74CriticalSectionDlg.h 类声明///////////////////////////////
public:
static UINT MyThread1(LPVOID lpParam);
static UINT MyThread2(LPVOID lpParam);
private:
static CRITICAL_SECTION m_criticalSection;
/////////////////////////////////////74CriticalSectionDlg.cpp 类定义/////////////////////////////
//初始化静态成员变量,该变量为结构体,静态成员变量作为结构体的初始化采用类似形式!
CRITICAL_SECTION CMy74CriticalSectionDlg::m_criticalSection = {0};
//对话框初始化
BOOL CMy74CriticalSectionDlg::OnInitDialog()
{
//codes
InitializeCriticalSection(&m_criticalSection); //初始化临界区
CWinThread* pThread1 = AfxBeginThread(MyThread1, (LPVOID)&m_ctrlEdit1); //开启两个线程
CWinThread* pThread2 = AfxBeginThread(MyThread2, (LPVOID)&m_ctrlEdit2);
//codes
}
//子线程1
UINT CMy74CriticalSectionDlg::MyThread1(LPVOID lpParam)
{
CString str;
int a = 0;
CEdit* pEdit = (CEdit*)lpParam;
while (true)
{
EnterCriticalSection(&m_criticalSection); //等待进入临界区,进入后加锁使其他线程不能进入
str.Format("%d", ++a);
str += " a";
pEdit->SetWindowText(str);
Sleep(100);
if (a >= 1000)
{
LeaveCriticalSection(&m_criticalSection); //当a>=1000时线程1退出,如果不加此句则线程2永远不能进入临界区
break;
}
LeaveCriticalSection(&m_criticalSection); //离开 开锁
}
return 0;
}
//子线程2
UINT CMy74CriticalSectionDlg::MyThread2(LPVOID lpParam)
{
CString str;
int b = 0;
CEdit* pEdit = (CEdit*)lpParam;
while (true)
{
EnterCriticalSection(&m_criticalSection);//等待进入临界区,进入后加锁
str.Format("%d", ++b);
str += " b";
pEdit->SetWindowText(str);
Sleep(100);
LeaveCriticalSection(&m_criticalSection); //离开 开锁
}
return 0;
}
NOTE:如果子线程1或2中调用了多次EnterCriticalSection,在线程退出或一次循环结束时也要调用多次LeaveCriticalSection。
线程同步CriticalSection的更多相关文章
- Delphi多线程编程--线程同步的方法(事件、互斥、信号、计时器)简介
更详细的可以参考:http://www.cnblogs.com/xumenger/p/4450659.html 或者参考之后的博客 四个系统内核对象(事件.互斥.信号.计时器)都是线程同步的手段,从这 ...
- Delphi 线程同步技术(转)
上次跟大家分享了线程的标准代码,其实在线程的使用中最重要的是线程的同步问题,如果你在使用线程后,发现你的界面经常被卡死,或者无法显示出来,显示混乱,你的使用的变量值老是不按预想的变化,结果往往出乎意料 ...
- Windows API学习---用户方式中的线程同步
前言 当所有的线程在互相之间不需要进行通信的情况下就能够顺利地运行时, Micrsoft Windows的运行性能最好.但是,线程很少能够在所有的时间都独立地进行操作.通常情况下,要生成一些线程来处理 ...
- windows线程同步的总结
一 线程 1)如果你正在编写C/C++代码,决不应该调用CreateThread.相反,应该使用VisualC++运行期库函数_beginthreadex,退出也应该使用_endthreadex.如果 ...
- windows lua 多线程 线程同步
今天在改一个程序,改成部分逻辑用lua写,这个程序是多线程的.将程序中部分逻辑改成lua之后,各种非法访问内存错误,各种奇奇怪怪的问题,不分时间,不分地点的出现崩溃.从调用堆栈来看,基本都是使用lua ...
- java线程 同步临界区:thinking in java4 21.3.5
java线程 同步临界区:thinking in java4 21.3.5 thinking in java 4免费下载:http://download.csdn.net/detail/liangru ...
- MFC线程(二):线程同步临界区CRITICAL SECTION
当多个线程同时使用相同的资源时,由于是并发执行,不能保证先后顺序.所以假如时一个公共变量被几个线程同时使用会造成该变量值的混乱. 下面来举个简单例子. 假如有一个字符数组变量 char g_charA ...
- Java多线程 | 02 | 线程同步机制
同步机制简介 线程同步机制是一套用于协调线程之间的数据访问的机制.该机制可以保障线程安全.Java平台提供的线程同步机制包括: 锁,volatile关键字,final关键字,static关键字,以 ...
- [ 高并发]Java高并发编程系列第二篇--线程同步
高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...
随机推荐
- 洛谷 P2611 [ZJOI2012]小蓝的好友 解题报告
P2611 [ZJOI2012]小蓝的好友 题目描述 终于到达了这次选拔赛的最后一题,想必你已经厌倦了小蓝和小白的故事,为了回馈各位比赛选手,此题的主角是贯穿这次比赛的关键人物--小蓝的好友. 在帮小 ...
- 常见编程语言对REPL支持情况小结
最近跟一个朋友聊起编程语言的一些特性,他有个言论让我略有所思:“不能REPL的都是渣”.当然这个观点有点偏激,但我们可以探究一下,我们常用的编程语言里面,哪些支持REPL,哪些不支持,还有REPL的一 ...
- Codeforces Round #535 (Div. 3) 题解
Codeforces Round #535 (Div. 3) 题目总链接:https://codeforces.com/contest/1108 太懒了啊~好久之前的我现在才更新,赶紧补上吧,不能漏掉 ...
- POJ1062:昂贵的聘礼(dfs)
昂贵的聘礼 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 58108 Accepted: 17536 题目链接:http ...
- Ubuntu修改grub启动顺序和启动时间
sudo gedit /boot/grub/grub.cfg,输入密码,在弹出的文件中找到set default = "0",想要改为第N项默认就把0改成N-1 看到启动界面是第几 ...
- org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.oskyhang.gbd.service.UserService] found for dependency: expected at least 1 bean which qualifies as aut
spring中一个符号的错误居然让我浪费了四五个小时才找出来,不得不给自己了两个耳光.. 由于新建项目与原来项目的目录结构有所不同,copy过来的配置文件,有些地方修改的不彻底,导致spring扫描注 ...
- oracle数据库cmd导出数据和导入数据
一:前言 每次我自己来导出oracle数据的数据进行备份的时候都是要看一遍记载的语句,还别说自己敲多了,也熟练了,但是还是不是很放心,所以就记载下来吧. 二:内容 (1).最简单,最直接的导入方式(这 ...
- php连接mysql报错——Fatal error: Call to undefined function mysql_connect() in
练习php连接mysql数据库 代码:mysql_connect("127.0.0.1:3306","root", ..... 浏览器报错:Fatal erro ...
- HDU2481 Toy
Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission ...
- [BZOJ1010][HNOI2008]玩具装箱toy 解题报告
Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1... ...