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

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

      临界区(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. caioj 1070 动态规划入门(二维一边推3:字符距离)(最长公共子序列拓展)

    复制上一题总结 caioj 1069到1071 都是最长公共字序列的拓展,我总结出了一个模型,屡试不爽    (1) 字符串下标从1开始,因为0用来表示字符为空的情况,而不是第一个字符     (2) ...

  2. 洛谷 P1176 路径计数2

    P1176 路径计数2 题目描述 一个N×N的网格,你一开始在(1, 1),即左上角.每次只能移动到下方相邻的格子或者右方相邻的格子,问到达(N, N),即右下角有多少种方法. 但是这个问题太简单了, ...

  3. spring AOP的Pointcut注解报错

    error at ::0 can't find referenced pointcut spring使用的是4.1.0,在项目中直接复制旧的aspectjweave.jar报错了 然后换成aspect ...

  4. 【LeetCode OJ 14】Longest Common Prefix

    题目链接:https://leetcode.com/problems/longest-common-prefix/ 题目:Write a function to find the longest co ...

  5. Java之——删除ArrayList中的反复元素的2种方法

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47414935 ArrayList是Java中最经常使用的集合类型之中的一个.它同意 ...

  6. 线程池系列一:线程池作用及Executors方法讲解

    线程池的作用: 线程池作用就是限制系统中执行线程的数量.     根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果:少了浪费了系统资源,多了造成系统拥挤效率不高.用线程池控制线程数量 ...

  7. BZOJ 2836 树链剖分+线段树

    思路: 链剖+线段树裸题 重链的标号就是DFS序 所以查子树的时候每回就 query(change[x],change[x]+size[x]-1) 就好了 剩下的应该都会吧.. //By Sirius ...

  8. 2015上海网络赛 HDU 5475 An easy problem 线段树

    题意就不说了 思路:线段树,维护区间乘积.2操作就将要除的点更新为1. #include<iostream> #include<cstdio> #include<cstr ...

  9. Oracle 导入导出 创建用户等

    localhost:1158/emD:\app\Administrator\product\11.2.0\dbhome_1\bin\imp.exe log  path  E:\app\Administ ...

  10. 开发板ping得通本地,但是不能上网

    在3531D的开发板上面接入LAN7500的USB转以太网口,加载完驱动后. 然后开启eth1 查看一下ifconfig,发现没有ip,配置一下ip 直接ping本地发现可以ping得通,代表链路是连 ...