Win32多线程之临界区(Critical Sections)
来源:互联网 发布:nginx 配置http 307 编辑:程序博客网 时间:2024/06/17 13:00
Win32之中最容易使用的一个同步机制就是 critical sections。所谓critical sections意思是指一小块“用来处理一份呗共享的资源”的程序代码。这里所谓的资源,并不是指.res(资源文件)的Windows资源,而是广义上地指一块内存,一个数据结构,一个文件,或任何其他具有“使用之排他性”的东西。也就是说,“资源”每一次(同一时间内)只能够被一个线程处理。
你可能必须在程序的许多地方处理这一块共享的资源,所有这些程序代码可以被同一个critical section保护起来。为了阻止问题发生,一次只能有一个线程获准 进入critical section中(相对地也就是说资源受到了保护)。实施的方式是在程序中加上“进入”或“离开”critical section 的操作,如果有一个线程已经“进入“某个critical section,另外一个线程就绝对不能够进入同一个critical section。
在Win32程序中,你可以为每一个需要保护的资源声明一个CRITICAL_SECTION类型的变量。这个变量扮演红绿灯的角色,让同一时间内只有一个线程进入critical section。
Critical section并不是核心对象。因此,没有所谓handle这样的东西。它和核心对象不同,它存在于进程的内存空间中。你不需要使用像”Create“这样的API函数获得一个critical sectionhandle,你应该做的事将一个类型为CRITICAL_SECTION的局部变量初始化,方法是调用InitializeCriticalSection():
VOID InitializeCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
);
参数:
lpCriticalSection: 一个指针,指向欲被初始化的CRITICAL_SECTION变量,这个变量应该在你的程序中定义。
返回值:void。
下面就是一个基本的调用程序,用来产生并摧毁一个critical section。请注意:gCriticalSection被声明在程序的最上方,作为任一线程都可以使用的全局变量。
CRITICAL_SECTION gCriticalSection;
voidCreateDeleteCriticalSection()
{
InitializeCriticalSection(&gCriticalSection);
/* Do something here */
DeleteCriticalSection(&gCriticalSection);
}
一旦critical section被初始化,每一个线程就可以进入其中------只要它通过了EnterCriticalSection()这一关。
void EnterCriticalSection(
LPCRITICAL_SECTION lpCriticalSection ;
);
参数:
lpCriticalSection: 一个指针,指向一个你即将锁定的CRITICAL_SECTION变量。
返回值:void。
当线程准备好要离开critical section时,它必须调用LeaveCriticalSection():
void LeaveCriticalSection(&cs)(
LPCRITICAL_SECTION lpCriticalSection ;
);
参数:
lpCriticalSection: 一个指针,指向一个你即将解除锁定的CRITICAL_SECTION变量。
返回值:void。
延续刚才的例子,下面是使用临界区的一个例子:
void UpdateData()
{
EnterCriticalSection(&gCriticalSection);
/* Update the resource */
LeaveCriticalSection(&gCriticalSection);
}
你可能会发现,有好几个函数都需要进入同一个critical section(以上而言指的就是gCriticalSection)中,它们都前后包夹着Enter/Leave函数,并使用相同的参数,你应该在每一个存取全局数据的地方使用Enter/Leave函数。有时候Enter/Leave甚至会在同一个函数中出现数次------如果这个函数需要很长的运行时间。下面是一个互斥访问链表的一个例子:
typedef struct _Node
{
struct _Node *next;
int data;
} Node;
typedef struct _List
{
Node *head;
CRITICAL_SECTION critical_sec;
} List;
List *CreateList()
{
List *pList = (List *)malloc(sizeof(pList));
pList->head = NULL;
InitializeCriticalSection(&pList->Critical_sec);
return pList;
}
void DeleteList(List *pList)
{
DeleteCriticalSection(&pList->critical_sec);
free(pList);
}
void AddHead(List *pList,Node *node)
{
EnterCriticalSection(&pList->critical_sec);
node->next = pList->head;
pList->head = node;
LeaveCriticalSection(&pList->critical_sec);
}
void Insert(List *pList, Node *afterNode, Node *newNode)
{
EnterCriticalSection(&pList->critical_sec);
if( afterNode == NULL)
{
AddHead(pList, newNode);
}
else
{
newNode->next = afterNode->next;
afterNode->next = newNode;
}
LeaveCriticalSection(&pList->critical_sec);
}
Node *Next(List *pList, Node *node)
{
Node *next;
EnterCriticalSection(&pList->critical_sec);
next = node->next;
LeaveCriticalSection(&pList->critical_sec);
return next;
}
加上了额外的 的critical section操作之后,同一时间内最多只有一个人能够读或写链表内容。请注意,我把CRITICAL_SECTION 变量放在List结构之中,你也可以使用一个全局变量取代之,但我是希望一个链表实体都能够独立地读写,如果只使用一个全局性的critical section,就表示一次只能读写一个链表,这回产生效率上的严重问题。
你或许纳闷,为什么Next()也需要环绕一个critical section,毕竟它只是处理单一一个值而已。请注意,return node->next 实际上被编译为数个机器指令,而不是一个”原子操作“(所谓的atomic operation)。如果我们在前后加上critical section的保护,就能够强迫该操作成为”不可分割的“。
上述程序代码存在一个微妙点。在Next离开critical section之后,但尚未return之前,没有什么东西能够保护这个node免受另一个线程的删除操作,这个问题可以靠更高阶的"readers/writers锁定"来解决,我们将在后面解释怎么做。
这个简短的例子也说明了Win32 critical section的另一个性质,一旦线程进入critical section,它就能够一再地重复进入该critical section。这也就是为什么Insert()可以调用AddHead()而不需要先调用LeaveCriticalSection()的缘故。唯一的警告就是,每一个”进入“操作都必须有一个对应的”离开“操作,如果某个线程调用EnterCriticalSection()5次,它也必须调用LeaveCriticalSection()5次,该critical section才能够被释放。
- Win32多线程之临界区(Critical Sections)
- 多线程(C++)临界区Critical Sections问题
- critical sections 临界区(危险区)
- 多线程之临界区(Critical Section)
- Win32 Thread API学习之Critical Sections
- 使用临界区(Critical sections)给临界资源加锁
- 说说win32多线程锁之临界区
- win32多线程锁之临界区
- 多线程--同步(Critical Section临界区)
- 引用 多线程--同步(Critical Section临界区)
- window下线程同步之(Critical Sections(关键代码段、关键区域、临界区域)
- Windows线程同步之临界区对象(Critical Section)
- Windows Via C/C++:用户模式下的线程同步——临界区 Critical Sections
- 临界区(critical region)
- 临界区Critical Section
- Break Free of Code Deadlocks in Critical Sections Under Windows : 解开Windows下的临界区中的代码死锁
- Win32多线程下—临界区
- 多线程同步之CRITICAL_SECTION(临界区)
- 关于win8的flash问题
- win32串口同步、异步编程
- ADO.NET(二) oracle数据库链接、和Oracle.DataAccess.dll 有关异常的各种问题
- 自学JSP之摸索篇
- 《Effective C++》学习笔记条款03 尽可能使用const
- Win32多线程之临界区(Critical Sections)
- B. Students and Shoelaces
- WEB应用中的SESSION知多少?
- 【PAT】1024. Palindromic Number 回文反转相加
- 巧用减1和位与运算
- VC6 中编译使用 pjsip 的工程
- Php study1
- 访问内网问题
- Leetcode Populating Next Right Pointers in Each Node II