22-线程同步:关键代码段

线程同步:关键代码段

关键代码段,也称为临界区,工作在用户方式下。它是指一个小代码段,在代码能够执行前,它必须独占对某些资源的访问权。通常把多线程中访问同一种资源的那部分代码当做关键代码段。

注意:关键代码段不是内核对象,只是用户态下保证资源只能被独立访问的代码加锁。

步骤:先创建关键代码段(本质是一个结构体),再在需要加锁的代码前进入临界区,在结束该段代码后离开临界区,能让其它线程能够进入(同一代码段标识的)临界区。

1.初始化关键代码段InitializeCriticalSection

先声明结构体CRITICAL_SECTION,再将其地址传入

参数:

  • 一个指向 CRITICAL_SECTION 结构体的指针

2.进入关键代码段EnterCriticalSection

参数:

  • 一个指向 CRITICAL_SECTION 结构体的指针

3.退出关键代码段LeaveCriticalSection

参数:

  • 一个指向 CRITICAL_SECTION 结构体的指针

4.删除临界区DeleteCriticalSection

参数:

  • 一个指向 CRITICAL_SECTION 结构体的指针

案例

创建临界区结构体,在关键代码段前加锁,离开后解锁

#include <stdio.h>
#include <windows.h>
#include <process.h>
int iTickets = 5000;
CRITICAL_SECTION g_cs;
// A窗口 B窗口
DWORD WINAPI SellTicketA(void* lpParam)
{
while (1)
{
EnterCriticalSection(&g_cs);//进入临界区
if (iTickets > 0)
{
Sleep(1);
iTickets--;
printf("A remain %d\n", iTickets);
LeaveCriticalSection(&g_cs);//离开临界区
}
else
{
LeaveCriticalSection(&g_cs);//离开临界区
break;
}
}
return 0;
}
DWORD WINAPI SellTicketB(void* lpParam)
{
while (1)
{
EnterCriticalSection(&g_cs);//进入临界区
if (iTickets > 0)
{
Sleep(1);
iTickets--;
printf("B remain %d\n", iTickets);
LeaveCriticalSection(&g_cs);//离开临界区
}
else
{
LeaveCriticalSection(&g_cs);//离开临界区
break;
}
}
return 0;
}
int main()
{
HANDLE hThreadA, hThreadB;
hThreadA = CreateThread(NULL, 0, SellTicketA, NULL, 0, NULL); //2
hThreadB = CreateThread(NULL, 0, SellTicketB, NULL, 0, NULL); //2
CloseHandle(hThreadA); //1
CloseHandle(hThreadB); //1
InitializeCriticalSection(&g_cs); //初始化关键代码段
Sleep(40000);
DeleteCriticalSection(&g_cs);//删除临界区
system("pause");
return 0;
}