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

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

      临界区(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. easyui-combobox实现取值范围的联动

    需求:需要用两个combobox来输入一个年月的范围,下拉框的内容从服务器获取.需要实现选中前者后,后者的下拉框中不能显示比前者数值小的:选中后者后,前者的下拉框内容不能显示比后者数值大的 有两个co ...

  2. 题解 P3374 【【模板】树状数组 1】

    恩,这是AC的第一道树状数组呢. 本蒟蒻以前遇到RMQ问题一般都用线段树或ST表,可惜ST表不支持在线修改,而线段树代码量又太大. 如今终于找到了折中方案:树状数组!!!!代码量小,还支持修改! 树状 ...

  3. 洛谷 P1769 淘汰赛制_NOI导刊2010提高(01)

    P1769 淘汰赛制_NOI导刊2010提高(01) 题目描述 淘汰赛制是一种极其残酷的比赛制度.2n名选手分别标号1,2,3,…,2^n-1,2^n,他们将要参加n轮的激烈角逐.每一轮中,将所有参加 ...

  4. 微软CEO纳德拉拥抱Linux意欲何为?

    "我不喜欢打一场过时的战争."微软 CEO 萨蒂亚·纳德拉说道,"我想要打一场全新的战役." 上周日晚上.萨蒂亚·纳德拉来到旧金山 North Beach 区的 ...

  5. Magento--判断checkout中是否使用了coupon code

    在checkout页面中,如果想判断顾客是否有使用coupon code,可以通过checkout session来进行判断.以下代码会返回checkout中使用的coupon code或者返回空(当 ...

  6. 2.cocos设置背景图片

    在bool HelloWorld::init()中加入如下代码 auto bg = Sprite::create("1.jpg"); if (bg) { bg->setPos ...

  7. 获取windows版本信息的做法

    作者:朱金灿 来源:http://blog.csdn.net/clever101 个人不建议用 GetVersion 或GetVersionEx 之类的 API 来获取系统版本号.注意微软也说过,这个 ...

  8. XML之序列化C#实体类,DataTable,List

    1. static void Main(string[] args) { #region 实体类 Request patientIn = new Request(); patientIn.System ...

  9. AIX 压缩与归档

    .tar.Z 格式 压缩:  compress filename.tar 解压:  zcat filename.tar.Z           tar -xvf -   .tar.gz 格式 压缩:t ...

  10. java关于File.separator

    写好代码在模拟环境下测试,完全没问 题:但linux+tomcat下用的时候,却老是报告“No such file or diretory ”的异常,上传不了.后来发现是文件路径的问题.我的模拟测试环 ...