首页 > 其他分享 >MFC---多线程(线程同步之信号量)

MFC---多线程(线程同步之信号量)

时间:2024-01-16 16:32:59浏览次数:28  
标签:--- NULL HANDLE 信号量 线程 信号 多线程 资源


内核对象的状态

触发状态(有信号状态),表示有可用资源。未触发状态(无信号状态),表示没有可用资源

工作原理

以一个停车场是运作为例。假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆不受阻碍的进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入一辆,如果又离开两辆,则又可以放入两辆,如此往复。这个停车系统中,每辆车就好比一个线程,看门人就好比一个信号量,看门人限制了可以活动的线程。假如里面依然是三个车位,但是看门人改变了规则,要求每次只能停两辆车,那么一开始进入两辆车,后面得等到有车离开才能有车进入,但是得保证最多停两辆车。对于Semaphore而言,就如同一个看门人,限制了可活动的线程数。

信号量的组成

①计数器:该内核对象被使用的次数

最大资源数量:标识信号量可以控制的最大资源数量(带符号的32位)

当前资源数量:标识当前可用资源的数量(带符号的32位)。即表示当前开放资源的个数(注意不是剩下资源的个数),只有开放的资源才能被线程所申请。但这些开放的资源不一定被线程占用完。比如,当前开放5个资源,而只有3个线程申请,则还有2个资源可被申请,但如果这时总共是7个线程要使用信号量,显然开放的资源5个是不够的。这时还可以再开放2个,直到达到最大资源数量。

信号量的规则如下:

(1)如果当前资源计数大于0,那么信号量处于触发状态(有信号状态),表示有可用资源。

(2)如果当前资源计数等于0,那么信号量属于未触发状态(无信号状态),表示没有可用资源。

(3)系统绝对不会让当前资源计数变为负数

(4)当前资源计数绝对不会大于最大资源计数

MFC---多线程(线程同步之信号量)_内核对象

信号量与互斥量不同的地方是,它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目。信号量对象对线程的同步方式与前面几种方法不同,信号允许多个线程同时使用共享资源。

创建信号量

HANDLE
WINAPI
CreateSemaphoreW(
    _In_opt_ LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,  // Null 安全属性
_In_ LONG lInitialCount,  //初始化时,共有多少个资源是可以用的。 0:未触发状//态(无信号状态),表示没有可用资源

    _In_ LONG lMaximumCount,  //能够处理的最大的资源数量   3
    _In_opt_ LPCWSTR lpName   //NULL 信号量的名称
);

增加信号量

WINAPI
ReleaseSemaphore(
    _In_ HANDLE hSemaphore,   //信号量的句柄
    _In_ LONG lReleaseCount,   //将lReleaseCount值加到信号量的当前资源计数上面 0-> 1
    _Out_opt_ LPLONG lpPreviousCount  //当前资源计数的原始值
);

关闭句柄

CloseHandle(
    _In_ _Post_ptr_invalid_ HANDLE hObject
    );
#include <stdio.h>
#include <windows.h>
#include <process.h>

unsigned WINAPI Read(void* arg);
unsigned WINAPI Accu(void* arg);

static HANDLE semOne;
static HANDLE semTwo;
static int num;

int main(int argc, char* argv[])
{
	HANDLE hThread1, hThread2;
	semOne = CreateSemaphore(NULL, 0, 1, NULL);
	//semOne 没有可用资源  只能表示0或者1的二进制信号量  无信号
	semTwo = CreateSemaphore(NULL, 1, 1, NULL);
	//semTwo 有可用资源,有信号状态   有信号
	hThread1 = (HANDLE)_beginthreadex(NULL, 0, Read, NULL, 0, NULL);
	hThread2 = (HANDLE)_beginthreadex(NULL, 0, Accu, NULL, 0, NULL);

	WaitForSingleObject(hThread1, INFINITE);
	WaitForSingleObject(hThread2, INFINITE);

	CloseHandle(semOne);
	CloseHandle(semTwo);
	system("pause");
	return 0;
}

unsigned WINAPI Read(void* arg)
{
	int i;
	for (i = 0; i < 5; i++)
	{
		fputs("Input num: ", stdout);  //  1   5   11
		printf("begin read\n"); // 3   6   12
		//等待内核对象semTwo的信号,如果有信号,继续执行;如果没有信号,等待
		WaitForSingleObject(semTwo, INFINITE); 
		printf("beginning read\n"); //4  10   16
		scanf("%d", &num);
		ReleaseSemaphore(semOne, 1, NULL);
	}
	return 0;
}
unsigned WINAPI Accu(void* arg)
{
	int sum = 0, i;
	for (i = 0; i < 5; i++)
	{
		printf("begin Accu\n");  //2    9   15
		//等待内核对象semOne的信号,如果有信号,继续执行;如果没有信号,等待
		WaitForSingleObject(semOne, INFINITE);
		printf("beginning Accu\n");  //7   13
		sum += num;
		printf("sum = %d \n", sum);  // 8   14
		ReleaseSemaphore(semTwo, 1, NULL);
	}
	printf("Result: %d \n", sum);
	return 0;
}


标签:---,NULL,HANDLE,信号量,线程,信号,多线程,资源
From: https://blog.51cto.com/u_15305087/9273782

相关文章

  • MFC---多线程(各种线程同步的比较总结)
    windows线程同步的方式主要有四种:互斥对象Mutex、事件对象event和关键代码段criticalSection,信号量对于上面介绍的三种线程同步的方式,它们之间的区别如下所述:●互斥对象和事件以及信号量都属于内核对象,利用内核对象进行线程同步时,速度较慢,但利用互斥对象和事件对象这样的内核对......
  • MFC---多线程(qq群聊的服务端和客户端)
    服务端//多线程+socket编程的一个联合使用//用互斥体进行线程同步socket编程临界区全局变量#include<WinSock2.h>#include<iostream>#include<windows.h>#include<process.h>#pragmacomment(lib,"ws2_32.lib")#defineMAX_CLNT256#defineMAX_BUF_S......
  • MFC---多线程(基本概念和线程同步之互斥对象)
    基本概念引入一个题目:Bingo老师提了一个需求:打印每隔3秒叫martin老师做一次俯卧撑持续20次每隔1秒钟叫rock老师甩头发持续50次每隔2秒钟叫西西老师唱歌持续40次线程(CPU调度和分派的基本单位)线程是在进程中产生的一个执行单元,是CPU调度和分配的最小单元,其在同一个进程中与......
  • C++---打开txt文件进行字符串的查找替换最终生成Excel文件
    #include<iostream>#include<fstream>#include<sstream>#include<string>#include<vector>#include<algorithm>#include<iomanip>usingnamespacestd;voidfindAndReplaceAll(string&source,conststring&......
  • MFC---多线程(线程同步之关键代码段)
    关键代码段,也称为临界区,工作在用户方式下。它是指一个小代码段,在代码能够执行前,它必须独占对某些资源的访问权。通常把多线程中访问同一种资源的那部分代码当做关键代码段。1.初始化关键代码段调用InitializeCriticalSection函数初始化一个关键代码段。InitializeCriticalSection(......
  • 方法论:仓储物流规划--数据分析(转)
     老K-LaoK专栏同名微信公众号:智能仓储物流技术研习社。​关注他 8人赞同了该文章导语大家好,我是智能仓储物流技术研习社的社长,你的老朋友,老K。知识星球 * 原创电子书 * 深海社区 * 微信群文:尹军琪在做物流规划设计时,人们往往对设计指标......
  • Unity FaceBook SDK - 1
    SDK下载前往https://developers.facebook.com/docs/unity/downloads下载SDKps目前我只用过16.0.0跑通 在facebook上搞出应用后,将应用的app相对于数据复制过来如图下: 安卓的话将上面的三个内容复制到facebook,然后点击一下按钮,生成出manifest 然后可以参考使......
  • svg使用封装-vue
    我们在项目中经常会使用到svg,这里对svg进行封装,以方便后续的使用。1.安装svg插件npmivite-plugin-svg-icons2.在vite.config.ts中引入,用来指定svg存放位置import{createSvgIconsPlugin}from"vite-plugin-svg-icons";import{resolve}from"path";constplugin......
  • AD采集卡设计方案:630-基于PCIe的高速模拟AD采集卡
     基于PCIe的高速模拟AD采集卡一、产品概述   基于PCIe的一款分布式高速数据采集系统,实现多路AD的数据采集,并通过PCIe传输到存储计算服务器,实现信号的分析、存储。    产品固化FPGA逻辑,适配2路1Gsps/2路2Gsps采集,实现PCIe的触发采集,单次采集容量2G......
  • (vcpu-0)Exception 0xc0000005 (access violation) has occurred
    VM安装window10报错如何解决?(vcpu-0)Exception0xc0000005(accessviolation)hasoccurred.(vcpu-1)Exception0xc0000005(accessviolation)hasoccurred.除了常规的虚拟化的一些原因外,如果网上的方式你都试过了,不能解决的话;那么请升级你的VMware到16.2.*版本即可;......