孙鑫 第十五/十六课之四 线程同步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的更多相关文章

  1. Delphi多线程编程--线程同步的方法(事件、互斥、信号、计时器)简介

    更详细的可以参考:http://www.cnblogs.com/xumenger/p/4450659.html 或者参考之后的博客 四个系统内核对象(事件.互斥.信号.计时器)都是线程同步的手段,从这 ...

  2. Delphi 线程同步技术(转)

    上次跟大家分享了线程的标准代码,其实在线程的使用中最重要的是线程的同步问题,如果你在使用线程后,发现你的界面经常被卡死,或者无法显示出来,显示混乱,你的使用的变量值老是不按预想的变化,结果往往出乎意料 ...

  3. Windows API学习---用户方式中的线程同步

    前言 当所有的线程在互相之间不需要进行通信的情况下就能够顺利地运行时, Micrsoft Windows的运行性能最好.但是,线程很少能够在所有的时间都独立地进行操作.通常情况下,要生成一些线程来处理 ...

  4. windows线程同步的总结

    一 线程 1)如果你正在编写C/C++代码,决不应该调用CreateThread.相反,应该使用VisualC++运行期库函数_beginthreadex,退出也应该使用_endthreadex.如果 ...

  5. windows lua 多线程 线程同步

    今天在改一个程序,改成部分逻辑用lua写,这个程序是多线程的.将程序中部分逻辑改成lua之后,各种非法访问内存错误,各种奇奇怪怪的问题,不分时间,不分地点的出现崩溃.从调用堆栈来看,基本都是使用lua ...

  6. java线程 同步临界区:thinking in java4 21.3.5

    java线程 同步临界区:thinking in java4 21.3.5 thinking in java 4免费下载:http://download.csdn.net/detail/liangru ...

  7. MFC线程(二):线程同步临界区CRITICAL SECTION

    当多个线程同时使用相同的资源时,由于是并发执行,不能保证先后顺序.所以假如时一个公共变量被几个线程同时使用会造成该变量值的混乱. 下面来举个简单例子. 假如有一个字符数组变量 char g_charA ...

  8. Java多线程 | 02 | 线程同步机制

    同步机制简介 ​ 线程同步机制是一套用于协调线程之间的数据访问的机制.该机制可以保障线程安全.Java平台提供的线程同步机制包括: 锁,volatile关键字,final关键字,static关键字,以 ...

  9. [ 高并发]Java高并发编程系列第二篇--线程同步

    高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...

随机推荐

  1. Codeforces 937.C Save Energy!

    C. Save Energy! time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...

  2. Python爬虫学习笔记之爬取新浪微博

    import requests from urllib.parse import urlencode from pyquery import PyQuery as pq from pymongo im ...

  3. matlab求最大公约数和最小公倍数

    最大公约数:(函数) function n = zuidagongyueshu(a,b) if(a>b) tem = a; b = a; a = tmp; end for i=1:a c = r ...

  4. [洛谷P1074] 靶形数独

    洛谷题目链接:靶形数独 题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教,Z 博 ...

  5. thinkpad x260 U盘进入

    主要有三个问题: 1.bios 不支持U盘启动 联想电脑bios设置u盘启动方法如下:1.打开联想笔记本电脑,在出现开机画面时按F2进入bios设置界面,使用左右方向键将光标移至security菜单, ...

  6. 【uva11468-Substring】AC自动机+dp

    http://acm.hust.edu.cn/vjudge/problem/31655 题意:给定k个模板串,n个字符以及选择它的概率pro[i],要构造一个长度问L的字符串s,问s不包含任意一个模板 ...

  7. [BZOJ3098]Hash Killer II解题报告

    这天天气不错,hzhwcmhf神犇给VFleaKing出了一道题:给你一个长度为N的字符串S,求有多少个不同的长度为L的子串.子串的定义是S[l].S[l + 1].... S[r]这样连续的一段.两 ...

  8. Linux : 多线程下载工具: axel

    wget 应该是最常用的下载工具了,但是其不支持多线程下载. axel 安装 epel 源有 axel 的二进制包,可以使用 yum 安装. yum install epel-release yum ...

  9. Swift学习三

    http://blog.csdn.net/kuloveyouwei/article/details/36005299 Swift 提供两种集合类型来存储集合,数组和字典.数组是一个同类型的序列化列表集 ...

  10. RabbitMQ消息队列(三): 发布/订阅

    1. 订阅/发布: 前面worker示例中的每个任务都是只发送给某一个worker,如果我们多个worker都需要接收处理同一个任务,此时就要使用 订阅/发布功能,比如,日志模块产生日志并发送到队列中 ...