我们也可以通过临界区保证在同一时间内只有一个线程对共享数据进行控制访问。临界区不是内核对象,只能对进程内部的线程进行同步。
临界区对象是定义在数据段中的一个CRITICAL_SECTION结构,Windows内部使用这个结构记录的一些信息,来确保同一个时间只有一个线程访问该临界区保护的数据。
临界区对象使用要调用的函数接口如下:
(1)InitializeCriticalSection()
void WINAPI InitializeCriticalSection(
_Out_ LPCRITICAL_SECTION lpCriticalSection
);
//lpCriticalSection:指向临界区对象的指针
创建CRITICAL_SECTION对象后,需要调用该函数进行临界区对象的初始化。任何线程在试图访问临界区所保护的资源之前,CRITICAL_SECTION结构对象的内部成员必须已经初始化。如果线程试图进入一个未经初始化的CRITICAL_SECTION,那么结果是不可预料的。
(2)EnterCriticalSection()
void WINAPI EnterCriticalSection(
_Inout_ LPCRITICAL_SECTION lpCriticalSection
);
//lpCriticalSection:指向临界区对象的指针
当线程要访问临界区所保护的数据的时候,必须首先调用该函数进入临界区,在同一时间,Windows只运行有一个线程进入临界区,如果调用EnterCriticalSection时,已经有线程在临界区内,那么会调用一个事件内核对象把调用线程切换到等待状态,这样调用线程不会浪费任何CPU时间,系统内核会记住这个线程想要访问的资源,当该资源可用时(另一个使用该资源的线程调用LeaveCriticalSection),系统会将等待中的线程切换回可调度的状态。
(3)TryEnterCriticalSection()
BOOL WINAPI TryEnterCriticalSection(
_Inout_ LPCRITICAL_SECTION lpCriticalSection
);
//lpCriticalSection:指向临界区对象的指针
//Return Value:表示是否进入临界区
TryEnterCriticalSection和EnterCriticalSection函数唯一的区别就是调用线程不会进入等待状态。如果共享资源真在被其他线程访问,那么该函数会返回FALSE,表示进入临界区失败,如果返回TRUE,表示已经进入临界区。
(4)LeaveCriticalSection()
void WINAPI LeaveCriticalSection(
_Inout_ LPCRITICAL_SECTION lpCriticalSection
);
//lpCriticalSection:指向临界区对象的指针
当线程完成了对共享资源的访问,应该调用该函数退出临界区,以便其他线程可以进行访问。
(5)DeleteCriticalSection()
void WINAPI DeleteCriticalSection(
_Inout_ LPCRITICAL_SECTION lpCriticalSection
);
//lpCriticalSection:指向临界区对象的指针
当程序不再使用临界区的时候,必须调用该函数将临界区对象删除。
使用临界区对象时有两点要注意:
-
任何访问共享资源的代码都应该放在EnterCriticalSection和LeaveCriticalSection之间,也就是这两个函数要成对出现,否则共享资源就有可能被破坏。
- 不要在临界区内运行较长时间,这样会影响程序的性能。
下面程序测试临界区功能:
#include <iostream>
#include <windows.h>
#include <process.h>
using namespace std;
CRITICAL_SECTION csTest;
volatile int flag = 0;
void CriticalSectionTest1(void *ptr)
{
EnterCriticalSection(&csTest);
flag = 1;
for (int i = 0; i < 5; ++i)
{
Sleep(1000);
cout<<flag<<' ';
}
LeaveCriticalSection(&csTest);
}
void CriticalSectionTest2(void *ptr)
{
EnterCriticalSection(&csTest);
flag = 2;
for (int i = 0; i < 5; ++i)
{
Sleep(1000);
cout<<flag<<' ';
}
LeaveCriticalSection(&csTest);
}
int main()
{
InitializeCriticalSection(&csTest);
_beginthread(CriticalSectionTest1, 0, NULL);
_beginthread(CriticalSectionTest2, 0, NULL);
Sleep(INFINITE);
DeleteCriticalSection(&csTest);
}
程序运行结果:
2 2 2 2 2 1 1 1 1 1
这里从运行结果可以看出,两个线程互斥的访问临界区资源,这里为了测试在进入临界区后调用Sleep函数, 但在实际程序中这种行为会严重影响程序的性能。
Jun 19, 2013 PM 22:58 @dorm
分享到:
相关推荐
vc++中使用临界区CriticalSection的例子.zip
使用临界区来实现多线程的同步互斥.critical section
[并发并行] [线程同步] [pthread和win32的临界区 Critical Section 比较] vs2010
简单的应用临界区对多线程程序中的公共变量进行保护的程序
本多线程是使用的临界区:CRITICAL_SECTION 按下按钮,通知线程要写入一串字符(线程执行完需要2s以上),延时20ms后通知线程再写入一串字符,跟第一次写入造成“冲突”,延时20ms后,在两个写都没完成时再通知线程...
临界区介绍以及多线程、多进程临界区调度原则、代码示例
A、临界区(Critical Section); B、互斥对象(Mutex); C、由 threadvar 声明的线程局部变量; D、信号量(Semaphore); 正确答案:C 2. 在多线程中使用临界区通常有五步(即:声明临界区变量、初始化临界区...
一、临界区(criticalsection) 1、临界区是线程同步的一种方式,即它在同一时刻只允许一个线程进入,其他线程只能等往此临界区被释放后才能进入,否则只能等待,线程也将挂起。需要注意的是临界区在同一线程中...
这是一个临界区类,实现线程同步。借用windowsAPI封装的一个小工具类,便于自己以后编程,这个类是以后的开始
多个线程交替执行输出各自的符号,本工程为方便支持26个线程,可循环 ...事件event + 临界区CriticalSection实现+标识量 事件event + 临界区CriticalSection实现 信号量Semaphore + 临界区CriticalSection实现
在应用程序中使用多个线程的一个好处是每个线程都可以异步执行。对于 Windows 应用程序,...线程同步有:临界区、互斥区、事件、信号量四种方式临界区(Critical Section)、互斥量(Mutex)、信号量(Semaphore)、
读写锁(读-读并发,读-写互斥,写-写互斥,基于CRITICAL_SECTION实现,简单高效,不支持进程间使用,写操作优先(即当前有线程在读,有写操作后,不允许再有新的读,直至写操作完成,避免写饿死))
[Delphi]多线程编程(8)多线程同步之CriticalSection(临界区).doc
这些技术包括临界区(Critical Section),互斥量(Mutex),信号量(Semaphore),事件Event等。 Event threading库中的event对象通过使用内部一个flag标记,通过flag的True或者False的变化来进行操作。 名称 ...
在Windows中,常见的同步对象有:信号量(Semaphore)、互斥量(Mutex)、临界段(CriticalSection)等。使用这些对象都分为三个步骤,一是创建或者初始化:接着请求该同步对象,随即进入临界区,这一步对应于互斥量的上锁...
在Windows中,常见的同步对象有:信号量(Semaphore)、互斥量(Mutex)、临界段(CriticalSection)等。使用这些对象都分为三个步骤,一是创建或者初始化:接着请求该同步对象,随即进入临界区,这一步对应于互斥量的上锁...
//临界区 CRITICAL_SECTION cs_Write; CRITICAL_SECTION cs_Read; struct ThreadInfo //线程信息 { int Threadhao; //线程序号 char ThreadClass; //线程类别 double ThreadStartTime; //线程开始时间 double ...
线程同步(Thread Synchronization)是并行编程中非常重要的通讯手段,其中最典型的应用就是用Pthreads提供的锁机制(lock)来对多个线程之间共 享的临界区(Critical Section)进行保护(另一种常用的同步机制是barrier)。
本文介绍C# lock关键字,C#提供了一个关键字lock,它可以把一段代码定义为互斥...它可以保证当一个线程在关键代码段的时候,另一个线程不会进来,它只能等待,等到那个线程对象被释放,也就是说线程出了临界区。用法:
通常情况下原子操作可以通过互斥的访问方式来保证,例如Linux下的互斥锁(mutex),Windows下的临界区(Critical Section)等。下面看一个Linux环境使用POSIX标准的pthread库实现多线程下的原子操作: #include #...