Windows多线程编程

news2024/9/20 18:34:28

一、 实验内容或题目:

以多线程编程的方式完成:
1)随机生成一个数组,求其平均值
2)随机生成一个数组,求其最大值
3)随机生成一个数组,求其最小值

二、 实验目的与要求:

上传的multi-thread.c已经以单线程的方式完成了上述工作。
请将之更改成多线程完成工作的方式,在数组长度较大的情况下,并观察单线程与多线程方式之间的时间对比。

三、 实验步骤:

需要使用的api:
_beginthread, CreateThread, WaitForSingleObject

四、 实验结果:

单进程
在这里插入图片描述
多进程(由于__declspec(thread)的限制,只能将generateNumbers()函数放入方法中,达到线程局部变量的效果)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五、 总结:

根据多次实验的结果,多线程所用的时间明显要小于单线程,多线程可同时运行多个程序,一定程度上提高了响应速度,更能充分利用CPU。

拓展思考

实验中使用了__declspec(thread)来标识pNumbers指针变量,请回答:
1)此标识符的作用是什么?
2)如果没有此标识符来修饰pNumbers指针变量,程序能运行正确吗?
答:
1) 声明一个线程局部变量,可以为每个线程生成一副本,使该变量不能被多个线程共享访问,各个线程使用各自的这个变量,互不影响。 为什么要使用这个声明符号,因为“C/C++运行库是在多线程程序出现的很多年前设计的,所以运行库中的很多函数都是不支持多线程的,所以在多线程的环境中使用运行库中的函数会发生各种各样的错误与缺陷,C/C++运行库的解决方案就是使用TLS”(TLS:Thread local Storage,线程局部存储区)。
2) 在单线程中有无都可运行,而在多线程中,添加了__declspec(thread)反而无法运行,查询了一些资料,可能是因为__declspec(thread)变量是在静态链接的时候确定存储位置的,如果动态加载,这些变量实际上都是空,地址可能是0或者任何数值。
我觉得,既然__declspec(thread)是用来声明线程局部变量的,因该把generateNumbers(cardinality)放在每个子进程调用的方法中,这样的化程序可以正确运行
直接将示例代码改成多线程版,数组依然用__declspec(thread)声明,程序无法运行,原因可能是这个。
在这里插入图片描述
在这里插入图片描述

源码

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h> 
#include <process.h>
#include <math.h>
#include <time.h>
#define Thread   __declspec( thread )

Thread int* pNumbers = NULL;

void generateNumbers(unsigned int cardinality) {
	pNumbers = (int*)malloc(cardinality * sizeof(unsigned int));
	assert(pNumbers);
	unsigned int iter;

	srand((unsigned int)time(NULL));
	for (iter = 0; iter < cardinality; iter++) {
		pNumbers[iter] = rand();
	}

	return;
}

void getMax(unsigned int cardinality) {
	unsigned int iter;
	unsigned int max = 0;
	for (iter = 0; iter < cardinality; iter++) {
		if (pNumbers[iter] > max) {
			max = pNumbers[iter];
		}
	}
	printf("Max is %d\n", max);
}

void getMin(unsigned int cardinality) {
	unsigned int iter;
	unsigned int min = UINT_MAX;
	for (iter = 0; iter < cardinality; iter++) {
		if (pNumbers[iter] < min) {
			min = pNumbers[iter];
		}
	}
	printf("Min is %d\n", min);
}

void getAvg(unsigned int cardinality) {
	unsigned int iter;
	unsigned long long sum = 0;
	for (iter = 0; iter < cardinality; iter++) {
		sum += pNumbers[iter];
	}
	printf("Average is %f\n", (float)(sum / cardinality));
}

unsigned int TimeOfMin, TimeOfMax, TimeOfAverage;

int main(int argc, char* argv[]) {
	if (argc < 2) {
		printf("input the cardinality of numbers to be processed.\n");
		return -1;
	}

	int cardinality = atoi(argv[1]);
	if (cardinality <= 0) {
		printf("please input a positive number as cardinality.\n");
		return -1;
	}
	else if (cardinality > 99999999) {
		printf("cardinality is too big to process.\n");
		return -1;
	}

	clock_t start = clock();

	{
		printf("creating %d numbers randomly\n", cardinality);
		generateNumbers(cardinality);
		getMax(cardinality);

		printf("creating %d numbers randomly\n", cardinality);
		generateNumbers(cardinality);
		getMin(cardinality);

		printf("creating %d numbers randomly\n", cardinality);
		generateNumbers(cardinality);
		getAvg(cardinality);
	}

	clock_t finish = clock();
	double duration = (double)(finish - start);

	/
	printf("Time collapsed: %f ms\n", duration);

	free(pNumbers);
	return 0;
}
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h> 
#include <process.h>
#include <math.h>
#include <time.h>
#define Thread __declspec( thread )

Thread int* pNumbers = NULL;

void generateNumbers(unsigned int cardinality) {
	pNumbers = (int*)malloc(cardinality * sizeof(unsigned int));
	assert(pNumbers);
	unsigned int iter;

	srand((unsigned int)time(NULL));
	for (iter = 0; iter < cardinality; iter++) {
		pNumbers[iter] = rand();
	}
	return;
}

void getMax(unsigned int cardinality) {
	unsigned int iter;
	unsigned int max = 0;
	generateNumbers(cardinality);
	for (iter = 0; iter < cardinality; iter++) {
		if (pNumbers[iter] > max) {
			max = pNumbers[iter];
		}
	}
	printf("Max is %d\n", max);
}
//当函数不允许接受参数时,必须使用void限定
void getMin(void* lpVoid) {
	unsigned int iter;
	unsigned int min = UINT_MAX;
	//获得cardinality
	unsigned int cardinality = (int)lpVoid;
	generateNumbers(cardinality);
	for (iter = 0; iter < cardinality; iter++) {
		if (pNumbers[iter] < min) {
			min = pNumbers[iter];
		}
	}
	printf("Min is %d\n", min);
}

void getAvg(void* lpVoid) {
	unsigned int iter;
	unsigned long long sum = 0;
	unsigned int cardinality = (int)lpVoid;
	generateNumbers(cardinality);
	for (iter = 0; iter < cardinality; iter++) {
		sum += pNumbers[iter];
	}
	printf("Average is %f\n", (float)(sum / cardinality));
}

unsigned int TimeOfMin, TimeOfMax, TimeOfAverage;

int main(int argc, char* argv[]) {
	HANDLE hThread1, hThread2;

	if (argc < 2) {
		printf("input the cardinality of numbers to be processed.\n");
		return -1;
	}

	int cardinality = atoi(argv[1]);
	if (cardinality <= 0) {
		printf("please input a positive number as cardinality.\n");
		return -1;
	}
	else if (cardinality > 99999999) {
		printf("cardinality is too big to process.\n");
		return -1;
	}

	clock_t start = clock();

	{
		//主线程
		printf("creating %d numbers randomly\n", cardinality);
		getMax(cardinality);

		//子线程1
		printf("creating %d numbers randomly\n", cardinality);
		HANDLE hThread1 = (HANDLE)_beginthread(getMin, 0, (void*)cardinality);
		WaitForSingleObject(hThread1, INFINITE);

		//子线程2
		printf("creating %d numbers randomly\n", cardinality);
		HANDLE hThread2 = (HANDLE)_beginthread(getAvg, 0, (void*)cardinality);
		WaitForSingleObject(hThread2, INFINITE);
	}

	clock_t finish = clock();
	double duration = (double)(finish - start);
	printf("Time collapsed: %f ms\n", duration);
	free(pNumbers);
	_endthread();
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/60542.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kaggle Feedback Prize 3比赛总结:如何高效使用hidden states输出(2)

比赛链接&#xff1a;https://www.kaggle.com/competitions/feedback-prize-english-language-learning 在Kaggle Feedback Prize 3比赛总结&#xff1a;如何高效使用hidden states输出(2)中介绍了针对last layer hidden state的各种pooling的方法。 在利用Transformer类的预…

Vue学习:Hello小案例

使用Vue的目的&#xff1a;构建用户界面&#xff08;需要使用容器 摆放这个界面的内容&#xff09; favicon.ico:1 GET http://127.0.0.1:5500/favicon.ico 404 (Not Found) 没有页签图标 在者服务器中 http://127.0.0.1:5500没有/favicon.ico 强制刷新网页&#xff1a;s…

3大经典分布式存储算法

文章目录1、背景2、算法2.1 分布存储之哈希取余算法2.2 分布式存储之一致性哈希算法2.3 分布式存储之哈希槽算法1、背景 一个经典的面试题目&#xff1a;1&#xff5e;2亿条数据需要缓存&#xff0c;请问如何设计这个方案&#xff1f; 回答&#xff1a;单台单机肯定不可能&…

Musical Christmas Lights——一个圣诞树灯光✨随音乐节奏改变的前端开源项目

文章目录前言视频介绍项目截图项目地址项目源码以上就是本篇文章的全部内容&#xff0c;将你编写好的项目分享给你的朋友们或者那个TA吧&#xff01;制作不易&#xff0c;求个三连&#xff01;❤️ &#x1f4ac; ⭐️前言 今天博主在刷短视频时&#x1f610;&#xff0c;朋友推…

VMware 虚拟机系统 与 win10 共享文件夹问题的解决

环境描述 本地&#xff1a;Win10 64位 VMware Workstation Pro 16 虚拟机&#xff0c;安装的 ubuntu 20.04 文件夹共享 win10 与 虚拟机的 ubuntu 共享文件夹&#xff0c;之前低版本的 VMware &#xff0c;安装 VMware Tools&#xff0c;并且 win10 端设置好工作目录后&…

秒级使网站变灰,不改代码不上线,如何做到?

注意&#xff1a;文本不是讲如何将网站置灰的那个技术点&#xff0c;那个技术点之前汶川地震的时候说过。 本文不讲如何实现技术&#xff0c;而是讲如何在第一时间知道消息后&#xff0c;更快速的实现这个置灰需求的上线。 实现需求不是乐趣&#xff0c;指挥别人去实现需求才…

广域网技术——SR-MPLS隧道保护技术

目录 TI-LFA FRR保护技术 LFA FRR R-LFA FRR TI-LFA FRR Anycast FRR技术 Host-Standby技术 VPN FRR技术 SR-MPLS防微环技术 场景一 SR本地正切防微环 场景二 SR本地回切防微环 场景三 SR远端正切防微环 场景四 SR远端回切防微环 TI-LFA和防微环的对比 TI-LFA FRR…

41. set()函数:将可迭代对象转换为可变集合

41. set()函数&#xff1a;将可迭代对象转换为可变集合 文章目录41. set()函数&#xff1a;将可迭代对象转换为可变集合1. set( )函数的作用2. set( )函数的语法3. set函数创建空集合4. set函数的参数只能是可迭代对象4.1 将字符串转换为集合4.2 set( )函数的参数不能为整数4.3…

MIT 6.S081 Operating System Lecture8 (非常随意的笔记)

系列文章目录 文章目录系列文章目录Page FaultCOPY ON WRITEPage Fault eager allocation 通常&#xff0c;因为应用程序无法非常准确地估计自己要增加的内存有多少&#xff0c;所以通常申请的内存会比真实要使用的内存要多。 在XV6中&#xff0c;sbrk的实现默认是eager alloc…

基于粒子群算法优化的lssvm回归预测-附代码

基于粒子群算法优化的lssvm回归预测 - 附代码 文章目录基于粒子群算法优化的lssvm回归预测 - 附代码1.数据集2.lssvm模型3.基于粒子群算法优化的LSSVM4.测试结果5.Matlab代码摘要&#xff1a;为了提高最小二乘支持向量机&#xff08;lssvm&#xff09;的回归预测准确率&#xf…

【C++】stack/queue/list

文章目录注意事项1 emplace 与 push 的区别一、stack&#xff08;栈&#xff09;&#xff08;先进后出、【头部插入、删除】、不许遍历&#xff09;1 基本概念&#xff08;栈是自顶向下(top在下)&#xff0c;堆是向上&#xff09;2 stack 常用接口&#xff08;构造函数、赋值操…

[蓝牙 Mesh Zephyr]-[005]-Key

[蓝牙 Mesh & Zephyr]-[005]-Key 1. Keys Mesh Profile specification 定义了 2 种key&#xff1a;application keys &#xff08;AppKey&#xff09;和 network keys&#xff08;NetKey&#xff09;。AppKeys 用于保护 upper transport layer 的通信安全&#xff0c;Net…

如何手动添加NLTK data

一、问题描述 Python的自然语言处理库NLTK在安装之后需要下载一些data文件才能使用。官方比较推荐的方式是直接运行下载data的代码&#xff1a; import nltk nltk.download(punkt) 但是实际操作之后发现由于网络原因无法下载成功。 除了运行代码之外&#xff0c;官方还推荐…

分布式队列celery学习

说明&#xff1a;本文内容来自《python自动化运维快速入门》学习 一、介绍 Celery是由纯Python编写的&#xff0c;但协议可以用任何语言实现。目前&#xff0c;已有Ruby实现的RCelery、Node.js实现的node-celery及一个PHP客户端&#xff0c;语言互通也可以通过using webhooks…

[附源码]JAVA毕业设计客户台账管理(系统+LW)

[附源码]JAVA毕业设计客户台账管理&#xff08;系统LW&#xff09; 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&…

Activiti7工作流(二)

流程定义相关 流程定义查询 查询流程相关信息&#xff0c;包含流程定义&#xff0c;流程部署&#xff0c;流程定义版本 Test public void testDefinitionQuery(){//创建ProcessEngine对象ProcessEngine processEngine ProcessEngines.getDefaultProcessEngine();//获取仓库…

自动识别验证码实现系统自动登录(可扩展实现无人自动化操作,如领取各个平台的优惠券),不依赖第三方可以支持离线识别处理,附源码可直接运行

自动识别验证码实现系统自动登录(可扩展实现无人自动化操作,如领取各个平台的优惠券),不依赖第三方可以支持离线识别处理,附源码可直接运行。 实现过程: 1、只要是图片验证码都支持识别; 2、通过百度API实现验证码识别;(依赖第三方,且需要连接互联网,内网不可用,实…

7-FreeRTOS软件定时器

1- 简介 1.1 软件定时器简述 软件定时器就是允许函数设置一定的等待时间&#xff0c;然后执行。定时器执行的函数被称为定时器的回调函数。定时器从启动到执行回调函数之间的时间称为定时器的周期。定时器的回调函数在定时器的时间到达时执行。 软件定时器要先创建才能使用。…

实战Docker未授权访问提权

1、fofa关键字 port“2375” && body“page not found” 2、docker -H tcp://ip:port 可查看到当前所有的实例 3、docker -H tcp://ip:port pull alpine 4、docker -H tcp://ip:port run -it --privileged alpine bin/sh 5、fdisk -l 查看其分区结构 6、创建一个…

Java安全-CC1

CC1 这里用的是组长的链子和yso好像不太一样&#xff0c;不过大体上都是差不多的。后半条的链子都是一样的&#xff0c;而且这条更短更易理解。yso的CC1过段时间再看一下。 环境 Maven依赖&#xff1a; <dependencies><dependency><groupId>commons-colle…