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

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

      临界区(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. JS文字特效:彩色滚动变幻效果,只适合少量的文字。(过多对页面有影响)

    JS代码如下: 代码具体是在哪里的我不知道但是我的有道云上有.如有哪位朋友知道,还望联系下,添加出处. <div id="chakhsu"></div> & ...

  2. 紫书 例题 10-9 UVa 1636 (概率计算)

    小学数学问题 记得分数比较的时候可以交叉相乘(同号) #include<cstdio> #include<cstring> #define REP(i, a, b) for(i ...

  3. 【Henu ACM Round#19 B】 Luxurious Houses

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 从右往左维护最大值. 看到比最大值小(或等于)的话.就递增到比最大值大1就好. [代码] #include <bits/std ...

  4. 三种记录 MySQL 所执行过的 SQL 语句的方法

    程式 Debug 有時後從前面第一行追起來很辛苦(程式碼太多或 compile 過), 另一種做法就是從後面追起來, 反正最後寫入的是 DB, 那就從 DB 開始往前推, 所以就是要抓程式是執行哪些 ...

  5. 国庆 day 6 上午

    1. 角谷猜想(kakutani.pas/c/cpp)(kakutani.in/out)时间限制:1s/空间限制:256M[题目描述] 某个名字末尾是 654321 的小 A 同学是个大家眼中公认的学 ...

  6. 利用socket模拟http的混合表单上传(在一个请求中提交表单并上传多个文件)

           在非常多企业级应用中,我们都没法直接通过开发语言sdk包封装的http工具来模拟http复合表单(multipart/form-data),特别是在跨语言跨平台的编程过程中.事实上实现方 ...

  7. 怎样查看电脑的IP地址

    在DOW窗体 :cmd->ipconfig 见截图:

  8. 文件的默认权限:umask

    1. 文件的默认权限 linux下当我们新建一个文件和文件夹时,该文件和文件夹的默认权限是什么? 通过umask命令来查看: $ umask 0002 $ umask -S u=rwx,g=rwx,o ...

  9. orm 通用方法——DeleteModel 主键删除

    定义代码: /** * 描述:删除对象 * 作者:Tianqi * 日期:2014-09-17 * param:model 对象实例,包含主键 * return:int 受影响行数 * return: ...

  10. 利用CORS实现跨域请求--转

    原文地址:http://newhtml.net/using-cors/ 跨域请求一直是网页编程中的一个难题,在过去,绝大多数人都倾向于使用JSONP来解决这一问题.不过现在,我们可以考虑一下W3C中一 ...