临界区
临界区(Critical Section)是一段独占对某些共享资源访问的代码,在任意时刻只允许一个线程对共享资源进行访问。如果有多个线程试图同时访问临界区,那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操作共享资源的目的。
临界区在使用时以CRITICAL_SECTION结构对象保护共享资源,并分别用EnterCriticalSection()和LeaveCriticalSection()函数去标识和释放一个临界区。所用到的CRITICAL_SECTION结构对象必须经过InitializeCriticalSection()的初始化后才能使用,而且必须确保所有线程中的任何试图访问此共享资源的代码都处在此临界区的保护之下。否则临界区将不会起到应有的作用,共享资源依然有被破坏的可能。
图1 使用临界区保持线程同步
下面通过一段代码展示了临界区在保护多线程访问的共享资源中的作用。通过两个线程来分别对全局变量g_cArray[10]进行写入操作,用临界区结构对象g_cs来保持线程的同步,并在开启线程前对其进行初始化。为了使实验效果更加明显,体现出临界区的作用,在线程函数对共享资源g_cArray[10]的写入时,以Sleep()函数延迟1毫秒,使其他线程同其抢占CPU的可能性增大。如果不使用临界区对其进行保护,则共享资源数据将被破坏(参见图1(a)所示计算结果),而使用临界区对线程保持同步后则可以得到正确的结果(参见图1(b)所示计算结果)。代码实现清单附下:
// 临界区结构对象 CRITICAL_SECTION g_cs; // 共享资源 char g_cArray[10]; UINT ThreadProc10(LPVOID pParam) { // 进入临界区 EnterCriticalSection(&g_cs); // 对共享资源进行写入操作 for (int i = 0; i < 10; i++) { g_cArray[i] = 'a'; Sleep(1); } // 离开临界区 LeaveCriticalSection(&g_cs); return 0; } UINT ThreadProc11(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 CSample08View::OnCriticalSection() { // 初始化临界区 InitializeCriticalSection(&g_cs); // 启动线程 AfxBeginThread(ThreadProc10, NULL); AfxBeginThread(ThreadProc11, NULL); // 等待计算完毕 Sleep(300); // 报告计算结果 CString sResult = CString(g_cArray); AfxMessageBox(sResult); } |
在使用临界区时,一般不允许其运行时间过长,只要进入临界区的线程还没有离开,其他所有试图进入此临界区的线程都会被挂起而进入到等待状态,并会在一定程度上影响。程序的运行性能。尤其需要注意的是不要将等待用户输入或是其他一些外界干预的操作包含到临界区。如果进入了临界区却一直没有释放,同样也会引起其他线程的长时间等待。换句话说,在执行了EnterCriticalSection()语句进入临界区后无论发生什么,必须确保与之匹配的LeaveCriticalSection()都能够被执行到。可以通过添加结构化异常处理代码来确保LeaveCriticalSection()语句的执行。虽然临界区同步速度很快,但却只能用来同步本进程内的线程,而不可用来同步多个进程中的线程。
MFC为临界区提供有一个CCriticalSection类,使用该类进行线程同步处理是非常简单的,只需在线程函数中用CCriticalSection类成员函数Lock()和UnLock()标定出被保护代码片段即可。对于上述代码,可通过CCriticalSection类将其改写如下:
// MFC临界区类对象 CCriticalSection g_clsCriticalSection; // 共享资源 char g_cArray[10]; UINT ThreadProc20(LPVOID pParam) { // 进入临界区 g_clsCriticalSection.Lock(); // 对共享资源进行写入操作 for (int i = 0; i < 10; i++) { g_cArray[i] = 'a'; Sleep(1); } // 离开临界区 g_clsCriticalSection.Unlock(); return 0; } UINT ThreadProc21(LPVOID pParam) { // 进入临界区 g_clsCriticalSection.Lock(); // 对共享资源进行写入操作 for (int i = 0; i < 10; i++) { g_cArray[10 - i - 1] = 'b'; Sleep(1); } // 离开临界区 g_clsCriticalSection.Unlock(); return 0; } …… void CSample08View::OnCriticalSectionMfc() { // 启动线程 AfxBeginThread(ThreadProc20, NULL); AfxBeginThread(ThreadProc21, NULL); // 等待计算完毕 Sleep(300); // 报告计算结果 CString sResult = CString(g_cArray); AfxMessageBox(sResult); } |
分享到:
相关推荐
线程同步技术编程小经验.rar
c++ 很好的多线程同步技术,值得学习!
多线程同步技术是计算机软件开发的重要技术,本文对多线程的各种同步技术的原理和实现进行了初步探讨。
45 <br/>Visual C++ 5.0中的多线程编程技术... 50 <br/>关于线程... 62 <br/>采用多线程进行数据采集... 64 <br/>循环创建多线程时保证参数的有效性... 67 <br/>MFC中多线程的应用... 70 ...
内部包含:mp3播放器Lrc歌词同步源程序代码分析、mp3播放器+支持歌词同步显示哦、简单音乐播放器。 mfc 解码 视频音频解码部分。 MFC_MultiSender_OVER 文件传送,多文件(超大文件)传送功能的实现,含文档。 ...
使用VC++多线程技术,线程通信、同步,实现对系统文件的搜索功能!!
内部包含:mp3播放器Lrc歌词同步源程序代码分析、mp3播放器+支持歌词同步显示哦、简单音乐播放器。 mfc 解码 视频音频解码部分。 MFC_MultiSender_OVER 文件传送,多文件(超大文件)传送功能的实现,含文档。 ...
内部包含:mp3播放器Lrc歌词同步源程序代码分析、mp3播放器+支持歌词同步显示哦、简单音乐播放器。 mfc 解码 视频音频解码部分。 MFC_MultiSender_OVER 文件传送,多文件(超大文件)传送功能的实现,含文档。 ...
软件在线升级程序的设计 用C++Builder 6.0实现远程控制 利用C#调用Microsoft.Win32命名空间中的类实现对注册表的读取管理 用C#开发手机短信收发程序 远程计算机重启原理及实现 VC++6.0下利用互斥量同步线程来...
第一课 Windows编程和面向对象技术 1.1 Windows发展历史 1.2 Windows操作系统特点 1.3 Windows应用程序设计的特点 ... 12.2 线程的同步 12.3 串行通信与重叠I/O 12.4 一个通信演示程序 12.5 小结
内部包含:mp3播放器Lrc歌词同步源程序代码分析、mp3播放器+支持歌词同步显示哦、简单音乐播放器。 mfc 解码 视频音频解码部分。 MFC_MultiSender_OVER 文件传送,多文件(超大文件)传送功能的实现,含文档。 ...
VC++编程指南(中文版),不错的一本电子书。啥也不说了,直接看内容预览: 第一课 Windows编程和面向对象技术 ... 12.2 线程的同步 12.3 串行通信与重叠I/O 12.4 一个通信演示程序 12.5 小结
内部包含:mp3播放器Lrc歌词同步源程序代码分析、mp3播放器+支持歌词同步显示哦、简单音乐播放器。 mfc 解码 视频音频解码部分。 MFC_MultiSender_OVER 文件传送,多文件(超大文件)传送功能的实现,含文档。 ...
内部包含:mp3播放器Lrc歌词同步源程序代码分析、mp3播放器+支持歌词同步显示哦、简单音乐播放器。 mfc 解码 视频音频解码部分。 MFC_MultiSender_OVER 文件传送,多文件(超大文件)传送功能的实现,含文档。 ...
5.2.1 未使用线程同步 5.2.2 利用事件同步 5.2.3 利用互斥同步 5.2.4 利用临界区同步 5.2.5 利用信号量同步 第6章 文件 6.1 文件基本操作 6.2 文件综合操作示例 6.3 内存映射文件 6.3.1 内存映射文件概述 ...
实现一个服务器对多个客户端的关键是,在服务端的使用集合CPtrList类用保存客户端的socket对象,思想与Java中的编程思想一样,只不过Java中会使用多线程技术,在Vector集合保存客户端的socket对象,而MFC框架提供了...
Visual C++线程同步技术剖析
第一课 Windows编程和面向对象技术 1.1 Windows发展历史 1.2 Windows操作系统特点 1.3 Windows应用程序设计的特点 ... 12.2 线程的同步 12.3 串行通信与重叠I/O 12.4 一个通信演示程序 12.5 小结
结合串口通信的机理和多线程同步方式,分析了Win32系统下多线程异步串口通信程序的开发方法. 1 引 言 串行通讯是计算机与其他设备进行数据交换时经常使用的方法之一,他具有实现简单,使用灵活方便,数据传输可靠...
第15章,线程同步:介绍多种线程同步技术,包括使用内核对象实现线程同步。 第16章,动态链接库:介绍DLL的基本原理,包括TLS机制。 第17章,结构化异常处理:介绍结构化异常处理机制,及其在VC++环境下的特性。 ...