在使用多线程时,一般非常少有多个线程全然独立的工作。往往是多个线程同一时候操作一个全局变量来获取程序的执行结果。多个线程同一时候訪问同一个全局变量,假设都是读取操作,则不会出现故障。

假设是写操作,则会错误发生。这时候,我们能够通过临界区,为全局变量设置一个保护,保证同一时候仅仅有一个线程能够訪问此变量。其它变量进入等待状态。

      临界区(Critical Section)是一段独占对某些共享资源訪问的代码,在随意时刻仅仅同意一个线程对共享资源进行訪问。假设有多个线程试图同一时候訪问临界区,那么在有一个线程进入后其它全部试图訪问此临界区的线程将被挂起。并一直持续到进入临界区的线程离开。临界区在被释放后,其它线程能够继续抢占。并以此达到用原子方式操作共享资源的目的。
      临界区在使用时以CRITICAL_SECTION结构对象保护共享资源,并分别用 ①InitializeCriticalSection(&cs); //初始化临界区②EnterCriticalSection(&cs);//进入临界区③LeaveCriticalSection(&cs);//离开临界区④DeleteCriticalSection(&cs);//删除临界区 
      一般类程序(举例)

// 临界区结构对象
CRITICAL_SECTION g_cs;
// 共享资源 
char g_cArray[10]

UINT ThreadProc1(LPVOID pParam)
{
 // 进入临界区
 EnterCriticalSection(&g_cs);
 // 对共享资源进行写入操作
 for (int i = 0; i < 10; i++)
 {
  g_cArray[i] = ’a’;
  Sleep(1);
 }
 // 离开临界区
 LeaveCriticalSection(&g_cs);
 return 0;
}

UINT ThreadProc2(LPVOID pParam)
{
 // 进入临界区
 EnterCriticalSection(&g_cs);
 // 对共享资源进行写入操作
 for (int i = 0; i < 10; i++)
 {
  g_cArray[10 - i - 1] = ’b’;
  Sleep(1);
 }
 // 离开临界区
 LeaveCriticalSection(&g_cs);
 return 0;
}

void CSampleView::OnCriticalSection() 
{
 // 初始化临界区
 InitializeCriticalSection(&g_cs);
 // 启动线程
 AfxBeginThread(ThreadProc1, NULL);
 AfxBeginThread(ThreadProc2, NULL);
 // 等待计算完成
 Sleep(300);
 // 报告计算结果
 CString sResult = CString(g_cArray);
 AfxMessageBox(sResult);
}

      在使用临界区时,一般不同意其执行时间过长,仅仅要进入临界区的线程还没有离开。其它全部试图进入此临界区的线程都会被挂起而进入到等待状态,并会在一定程度上影响。程序的执行性能。尤其须要注意的是不要将等待用户输入或是其它一些外界干预的操作包括到临界区。假设进入了临界区却一直没有释放,相同也会引起其它线程的长时间等待。换句话说。在执行了EnterCriticalSection()语句进入临界区后不管发生什么。必须确保与之匹配的LeaveCriticalSection()都能够被执行到。

能够通过加入结构化异常处理代码来确保LeaveCriticalSection
()语句的执行。尽管临界区同步速度非常快,但却仅仅能用来同步本进程内的线程,而不可用来同步多个进程中的线程。
      

      MFC为临界区提供有一个CCriticalSection类,使用该类进行线程同步处理是非常easy的,仅仅需在线程函数中用CCriticalSection类成员函数 Lock()和UnLock()标定出被保护代码片段就可以。对于上述代码,可通过CCriticalSection类将其改写例如以下:

       MFC应用(举例)

// MFC临界区类对象
CCriticalSection g_cs;
// 共享资源 
char g_cArray[10];
UINT ThreadProc1(LPVOID pParam)
{
 // 进入临界区
 g_cs.Lock();
 // 对共享资源进行写入操作
 for (int i = 0; i < 10; i++)
 {
  g_cArray[i] = ’a’;
  Sleep(1);
 }
 // 离开临界区
 g_cs.Unlock();
 return 0;
}
UINT ThreadProc2(LPVOID pParam)
{
 // 进入临界区
 g_cs.Lock();
 // 对共享资源进行写入操作
 for (int i = 0; i < 10; i++)
 {
  g_cArray[10 - i - 1] = ’b’;
  Sleep(1);
 }
 // 离开临界区
 g_cs.Unlock();
 return 0;
}
void CSampleView::OnCriticalSectionMfc() 
{
 // 启动线程
 AfxBeginThread(ThreadProc1, NULL);
 AfxBeginThread(ThreadProc2, NULL);
 // 等待计算完成
 Sleep(300);
 // 报告计算结果
 CString sResult = CString(g_cArray);
 AfxMessageBox(sResult);
}

VC多线程临界区的更多相关文章

  1. 《转》VC++多线程编程

    原地址:http://www.cnblogs.com/wxfasdic/archive/2010/09/23/1833522.html 留个纪念,不错的总结.十个例子清晰列举啦多线程编程的奥妙.  V ...

  2. VC++多线程编程

    一.问题的提出 编写一个耗时的单线程程序: 新建一个基于对话框的应用程序SingleThread,在主对话框IDD_SINGLETHREAD_DIALOG添加一个按钮,ID为IDC_SLEEP_SIX ...

  3. VC多线程编程

    一.问题的提出 编写一个耗时的单线程程序: 新建一个基于对话框的应用程序SingleThread,在主对话框IDD_SINGLETHREAD_DIALOG添加一个按钮,ID为IDC_SLEEP_SIX ...

  4. VC++ 多线程编程,win32,MFC 例子(转)

    一.问题的提出 编写一个耗时的单线程程序: 新建一个基于对话框的应用程序SingleThread,在主对话框IDD_SINGLETHREAD_DIALOG添加一个按钮,ID为IDC_SLEEP_SIX ...

  5. Java 多线程 临界区

    临界区表示一种公共资源或共享数据,可以被多个线程使用.但是每一次只能有一个线程使用它.一旦临界区资源被占用,想使用该资源的其他线程必须等待. 例如,办公室里的打印机一次只能执行一个任务.当小王和小明同 ...

  6. 【转】VC 多线程中控制界面控件的几种方法

    原文网址:https://software.intel.com/zh-cn/blogs/2010/11/30/vc-3 为了保证界面的用户体验经常要把数据处理等放到子线程中进行,然后把结果更新到主界面 ...

  7. VC多线程的用法

    .h 文件 #define WM_TEST    WM_USER + 1 class CTestThread : public CWinThread { DECLARE_DYNCREATE(CTest ...

  8. VC++多线程--进程间通信

    1.邮槽 邮槽是windows系统提供的一种单向通信的机制,邮槽能传输的数据非常小,一般在400k左右. 创建邮槽 HANDLE CreateMailslot( LPCTSTR lpName, //指 ...

  9. 深入浅出Win32多线程程序设计之基本概念

    一.深入浅出Win32多线程程序设计之基本概念[转] 引言 从单进程单线程到多进程多线程是操作系统发展的一种必然趋势,当年的DOS系统属于单任务操作系统,最优秀的程序员也只能通过驻留内存的方式实现所谓 ...

随机推荐

  1. 洛谷——P1966 火柴排队

    https://www.luogu.org/problem/show?pid=1966 题目描述 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列 ...

  2. 洛谷 P2630 图像变换

    P2630 图像变换 题目描述 给定3行3列的图像各像素点灰度值,给定最终图像,求最短.字典序最小的操作序列. 其中,可能的操作及对应字符有如下四种: A:顺时针旋转90度: B:逆时针旋转90度: ...

  3. nginx和apache

    apache所占用的内存资源较多,并且处理较慢 apache的全部模块都支持动静态编译 apache对Fcgi的支持不好 apache不支持epoll apache相对于nginx是一个庞然大物 ng ...

  4. iOS Code Sign error: Provisioning profile can&#39;t be found 解决方式

    出现error的过程:在执行另外一个xcode项目重置了code sign.回到原来的项目的时候出现这个error 修复方法: targe-build settings-code signing id ...

  5. thinkphp里面使用原生php

    thinkphp里面使用原生php Php代码可以和标签在模板文件中混合使用,可以在模板文件里面书写任意的PHP语句代码 ,包括下面两种方式: 使用php标签 例如: {php}echo 'Hello ...

  6. spring 中国下载点

    http://repo.spring.io/libs-release-local/org/springframework/spring/ spring 中国下载点

  7. codefroces 873 B. Balanced Substring && X73(前缀和思想)

    B. Balanced Substring You are given a string s consisting only of characters 0 and 1. A substring [l ...

  8. 大吉大利,晚饭吃鸡!——accept关闭问题

    假期收尾了,学芽子们都军训了.一群张一山和周冬雨在校内晃晃悠悠,说起来春风十里也就军训比较有意思.对于我这种一年追一部剧的人,显然是有点对不住.在我假期任务即将圆满之际,我开始放慢脚步寻找生活的美妙时 ...

  9. javaScript for in循环遍历对象

    for循环常被我们用来遍历数组,而如何遍历对象呢? 这时就需要用到for in循环了 写一个遍历对象名简写如下: for(var xxx in ooo){console.log(xxx)} 其中xxx ...

  10. JS的解析与执行过程—全局预处理阶段之全局词法环境对象

    问题:有如下代码 var a = 1; function pop() { alert(a); var a = 5; } pop();//执行结果,弹出undefined 这段代码的执行结果为undef ...