类CCriticalSection的对象表示一个“临界区”,它是一个用于同步的对象,同一时刻只允许一个线程存取资源或代码区。临界区在控制一次只有一个线程修改数据或其它的控制资源时非常有用。例如,在链表中增加一个结点就只允许一次一个线程进行。通过使用CCriticalSection对象来控制链表,就可以达到这个目的。  

在运行性能比较重要而且资源不会跨进程使用时,建议采用临界区代替信号灯。有关在MFC中使用信号灯的详细信息,请参阅CMutex。使用CCriticalSection对象之前,需要构造它。在构造函数返回后,就可以使用临界区了。在使用完之后要调用UnLock函数。  

存取由CCriticalSection控制的资源时,要在资源的存取函数中定义一个CSingleLock型的变量。然后调用加锁对象的Lock成员函数(如CSingleLock::Lock)。此时,调用的线程要么获得对资源的存取权,要么等待他人释放资源等待加锁,或者等待他人释放资源,但又因为超时而加锁失败。这样就保证了一次只有一个线程在存取临界资源。释放资源只需调用成员函数UnLock(例如CSingleLock:Unlock),或让锁对象在作用范围之外。  

此外,可以单独地建立一个CCriticalSection对象,并在存取临界资源之前显式地存取它。这种方式有助于保持代码的清晰,但是更容易出错,因为程序员要记住在存取临界资源前加锁,存取之后开锁。  #include <afxmt.h>

使隶属于同一进程的各线程协调一致地工作称为线程的同步。MFC提供了多种同步对象,最常用的四种:

  • 临界区(CCriticalSection)
  • 事件(CEvent)
  • 互斥量(CMutex)
  • 信号量(CSemaphore)

本人目前只学习了临界区(CCriticalSection) 的使用,简单介绍如下:

当多个线程访问一个独占性共享资源时,可以使用“临界区”对象。任一时刻只有一个线程可以拥有临界区对象,拥有临界区的线程可以访问被保护起来的资源或代码段,其他希望进入临界区的线程将被挂起等待,直到拥有临界区的线程放弃临界区时为止,这样就保证了不会在同一时刻出现多个线程访问共享资源。

CCriticalSection类的用法非常简单,步骤如下:
 

  1. 定义CCriticalSection类的一个全局对象(以使各个线程均能访问),如CCriticalSection critical_section;
  2. 在访问需要保护的资源或代码之前,调用CCriticalSection类的成员Lock()获得临界区对象:
    critical_section.Lock();
    

    在线程中调用该函数来使线程获得它所请求的临界区。如果此时没有其它线程占有临界区对象,则调用Lock()的线程获得临界区;否则,线程将被挂起,并放入到一个系统队列中等待,直到当前拥有临界区的线程释放了临界区时为止。

  3. 访问临界区完毕后,使用CCriticalSection的成员函数Unlock()来释放临界区:
    critical_section.Unlock();
    

    再通俗一点讲,就是线程A执行到critical_section.Lock();语句时,如果其它线程(B)正在执行critical_section.Lock();语句后且critical_section. Unlock();语句前的语句时,线程A就会等待,直到线程B执行完critical_section. Unlock();语句,线程A才会继续执行。

下面再通过一个实例进行演示说明。

例程:  MultiThread8

  1. 建立一个基于对话框的工程MultiThread8,在对话框IDD_MULTITHREAD8_DIALOG中加入两个按钮和两个编辑框控件,两个按钮的ID分别为IDC_WRITEW和IDC_WRITED,标题分别为“写‘W’”和“写‘D’”;两个编辑框的ID分别为IDC_W和IDC_D,属性都选中Read-only;
  2. 在MultiThread8Dlg.h文件中声明两个线程函数:
    UINT WriteW(LPVOID pParam);
    UINT WriteD(LPVOID pParam);
    
  3. 使用ClassWizard分别给IDC_W和IDC_D添加CEdit类变量m_ctrlW和m_ctrlD;
  4. 在MultiThread8Dlg.cpp文件中添加如下内容:

    为了文件中能够正确使用同步类,在文件开头添加:

    #include "afxmt.h"
    

    定义临界区和一个字符数组,为了能够在不同线程间使用,定义为全局变量:

    CCriticalSection critical_section;
    char g_Array[10];
    

    添加线程函数:

    UINT WriteW(LPVOID pParam)
    {CEdit *pEdit=(CEdit*)pParam;pEdit->SetWindowText("");critical_section.Lock();//锁定临界区,其它线程遇到critical_section.Lock();语句时要等待//直至执行critical_section.Unlock();语句for(int i=0;i<10;i++){g_Array[i]=''W'';pEdit->SetWindowText(g_Array);Sleep(1000);}critical_section.Unlock();return 0;}UINT WriteD(LPVOID pParam)
    {CEdit *pEdit=(CEdit*)pParam;pEdit->SetWindowText("");critical_section.Lock();//锁定临界区,其它线程遇到critical_section.Lock();语句时要等待//直至执行critical_section.Unlock();语句for(int i=0;i<10;i++){g_Array[i]=''D'';pEdit->SetWindowText(g_Array);Sleep(1000);}critical_section.Unlock();return 0;}
  5. 分别双击按钮IDC_WRITEW和IDC_WRITED,添加其响应函数:
    void CMultiThread8Dlg::OnWritew()
    {CWinThread *pWriteW=AfxBeginThread(WriteW,&m_ctrlW,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);pWriteW->ResumeThread();
    }void CMultiThread8Dlg::OnWrited()
    {CWinThread *pWriteD=AfxBeginThread(WriteD,&m_ctrlD,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);pWriteD->ResumeThread();}

    由于代码较简单,不再详述。编译、运行该例程,您可以连续点击两个按钮,观察体会临界类的作用。

原文地址:http://blog.csdn.net/dongpanshan/article/details/7868921

CCriticalSection临界区的使用方法相关推荐

  1. 每天学一点 -- CCriticalSection临界区

    (转)类CCriticalSection的对象表示一个"临界区",它是一个用于同步的对象,同一时刻只允许一个线程存取资源或代码区.临界区在控制一次只有一个线程修改数据或其它的控制资 ...

  2. win32 临界区和简单实例Demo(win32版)

    一 win32 临界区 临界区是一种防止多个线程同时执行一个特定代码段的机制.如果有多个线程试图同时访问临界区,那么在有一个线程进入后其他的所有试图访问此临界区的线程将被挂起,并且一直持续到进入临界区 ...

  3. 操作系统锁的实现方法有哪几种_一文带你彻底了解同步和锁的本质

    谈到锁,离不开多线程,或者进程间的通信.为了更好地从底层原理去了解锁的机制,形成体系化的知识,这篇文章我会从进程间通信底层原理说起,然后介绍一下Java中各种线程通信的实现机制,最后做一个系统的总结. ...

  4. 【操作系统/OS笔记12】同步互斥的三种实现方法:禁用硬件中断、基于软件的解决方案、更高级的抽象

    本次笔记内容: 9.5 临界区 9.6 方法1:禁用硬件中断 9.7 方法2:基于软件的解决方案 9.8 方法3:更高级的抽象 文章目录 临界区 管理临界区的方法 方法1:禁用硬件中断 方法2:基于软 ...

  5. 多线程锁详解之【临界区】

    更多的锁介绍可以先看看这篇文章:多线程锁详解之[序章] 正文: 一般锁的类型可分为两种:用户态锁和内核态锁.用户态锁是指这个锁的不能够跨进程使用.而内核态锁就是指能够跨进程使用的锁.一般书中会说,wi ...

  6. VC5-高级音频函数

    2005-09-07 高级音频函数 - [VC专栏] 使用多媒体API,源文件中需要包含头文件 Mmsystem.h,在Project->Settings->Link->Object ...

  7. C#线程从陌生到熟悉(4)

    互斥与同步 今天我们来看互斥与同步,互斥与同步一直线程操作方面的至关重要的一部份.首先来看下他们之间的概念. 互斥和同步都是在并发环境下编程特有的问题.并发是指宏观上多个线程同时进行而某一时刻只有一个 ...

  8. 【转】自旋锁及其衍生锁

    原文网址:http://blog.chinaunix.net/uid-26126915-id-3032644.html 自旋锁 自旋锁(spinlock)是用在多个CPU系统中的锁机制,当一个CPU正 ...

  9. 四级计算机网络选择题,2015全国计算机等级考试四级计算机网络模拟选择题

    一.选择题 操作系统单选题 1.现代操作系统最基本的特征是 A.并发性 B.顺序性 C.封闭性 D.并行性 2.组成操作系统的主要部分通常是进程线程管理.内存管理.设备管理和 A.文件管理 B.P.V ...

最新文章

  1. 如何在同一台电脑上多个账户同时登陆MSN
  2. 深入探究Java中equals()和==的区别是什么
  3. 计算机视觉与深度学习 | Matlab实现ORBSLAM2(附完整代码)
  4. Dubbo的Provider配置
  5. Mysql存储过程(四)——异常处理
  6. CentOS 5.6 快速搭建LAMP
  7. 北京soul_Soul高智商情侣,机器人博士邂逅科技记者,跨越1200公里来相爱
  8. jQuery框架学习第八天:ASP.NET jQuery实施方案
  9. 映射date类型_SQLALchemy常见数据类型
  10. Android Studio support 26.0.0-alpha1 Failed to resolve: com.android.support:appcompat-v7:27.+ 报错解决方法
  11. 知道是骗子 !好要撞上去!别太得瑟,没啥么好
  12. 静态HTML网页作业模板 华为企业网站设计作品 静态学生网页设计作业简单网页制作
  13. 盘点(腾讯字节谷歌等大厂)面试中常见的智力题
  14. 图解迷宫算法(广度优先遍历)
  15. x86_64-w64-mingw32/bin/ld.exe: cannot find -lmsvcrt
  16. Landscape-施密特版图触发器设计
  17. [域] 大量日志错误,事件ID:1058 事件ID:1030
  18. 二进制与十进制转换器
  19. Vue项目关于省略号显示
  20. GROUP BY 条件查询最新时间记录

热门文章

  1. 《测试开发方法论》之 预判
  2. 镜头的呼吸效应及解决方法
  3. 逆战ajax和axios、fetch的区别
  4. 烽火服务器怎么进入bios系统,dell怎么进入bios详细操作教程
  5. JAVA路径中空格问题
  6. 银行跨数据中心数据库双活架构设计:五大难点攻克
  7. 【数据库】MySQL中的锁机制
  8. 初次联系导师短信模板_【干货分享】联系导师时应该注意什么?
  9. Jenkins持续集成PytestSelenium
  10. UITabBarController的selectedIndex属性不起作用?