windows多线程(四) 关键段 CriticalSection

参考:https://www.cnblogs.com/ay-a/p/8810766.html

windows多线程(四) 关键段 CriticalSection
一、问题回顾
我们上一篇文章最后的程序的输出 g_Count 的值不是每次都正确,原因是没有对全局资源 g_Count 进行互斥访问(就是同一时刻只能由一个线程访问),接下来我们就来说一下使用关键段来给全局资源加锁以实现互斥访问。
二、 关键段 CriticalSection 声明及相关函数
(一)CriticalSection 声明

CRITICAL_SECTION 关键段名字;  // eg: CRITICAL_SECTION cs;

CRITICAL_SECTION 结构说明

typedef RTL_CRITICAL_SECTION CRITICAL_SECTION;
typedef struct _RTL_CRITICAL_SECTION {
    PRTL_CRITICAL_SECTION_DEBUG DebugInfo;

    //
    //  The following three fields control entering and exiting the critical
    //  section for the resource
    //

    LONG LockCount;
    LONG RecursionCount;
    HANDLE OwningThread;        // from the thread's ClientId->UniqueThread
    HANDLE LockSemaphore;
    ULONG_PTR SpinCount;        // force size on 64-bit systems when packed
} RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION;

第一个参数:PRTL_CRITICAL_SECTION_DEBUG DebugInfo; 调试的时候用的,先不做介绍。

第二个参数:LONG LockCount; 初始化为-1,n表示有n个线程在等待。

第三个参数:LONG RecursionCount; 表示该关键段的拥有线程对此资源获得关键段次数,初为0。

第四个参数:HANDLE OwningThread; 即拥有该关键段的线程句柄

第五个参数:HANDLE LockSemaphore; 实际上是一个自复位事件。

第六个参数:ULONG_PTR SpinCount; 旋转锁的设置,用于多处理器。
(二)CriticalSection相关函数
1.函数功能:初始化,定义关键段变量后必须先初始化。
void InitializeCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);

2.函数功能:销毁,用完之后记得销毁。
void DeleteCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);

3.函数功能:进入关键区域,系统保证各线程互斥的进入关键区域。
void EnterCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);

4.函数功能:离开关关键区域
void LeaveCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);

三、实例
现在使用关键段来解决上面的问题,代码如下:

#include <stdio.h>
#include <windows.h>

const unsigned int THREAD_NUM = 50;
unsigned int g_Count = 0;
CRITICAL_SECTION cs; //声明关键段
DWORD WINAPI  ThreadFunc(LPVOID);

int main()
{
	InitializeCriticalSection(&cs);	// 初始化关键段
	HANDLE hThread[THREAD_NUM];
	for (int i = 0; i < THREAD_NUM; i++)
	{
		hThread[i] = CreateThread(NULL, 0, ThreadFunc, 0, 0, NULL); // 创建线程
	}
	WaitForMultipleObjects(THREAD_NUM, hThread, true, INFINITE);    //一直等待,直到所有子线程全部返回
	printf(" 总共 %d 个线程给 g_Count 的值加一,现在 g_Count = %d\n", THREAD_NUM, g_Count);
	DeleteCriticalSection(&cs);		//销毁关键段
	return 0;
}

DWORD WINAPI  ThreadFunc(LPVOID p)
{
	Sleep(50);
	EnterCriticalSection(&cs);  // 进入关键段
	g_Count++;
	LeaveCriticalSection(&cs);  // 离开关键段
	Sleep(50);

	return 0;
}

运行结果如下图所示,给全局资源 g_Count 加锁,实现互斥访问,就能够让每个线程正确给 g_Count 值加一 :
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值