(c++)线程的创建、互斥锁的使用、线程数组

news/2024/9/20 22:50:47 标签: c++

 1.创建10个线程,每个线程都做10万次全局变量num1++操作,然后输出这个全局变量,预想结果应该是100万。但是线程可能在cpu分配的一个时间片中做不完10万次+1的操作,这时候cpu会被其他线程抢占,由于num1++不是一个原子操作(操作过程中可能会发生中断),导致++其实没有做完,所以num1的最终结果会小于100万。

2.创建10个线程,每个线程都做10万次全局变量num2++操作,与前者不同的是,这次对num2++操作加入互斥锁,也就是让num2++成为一个“原子操作”(操作过程不会被中断),所以结果符合预期为100万

#include<iostream>
#include<thread>//使用thread包含这个库
#include<mutex>//使用互斥锁包含这个库

using namespace std;//不加这个的话每个标识符前都要添加 std:: 才能用

mutex mtx2;//用来给num2++的操作加互斥锁

//两个全局变量用于做累加操作
int num1 = 0;
int num2 = 0;


void increase1()//让全局变量num1累加100000次
{
	for (int i = 0; i < 100000; i++)
	{
		num1++;
	}
}
void increase2()//让全局变量num2累加100000次
{
	for (int i = 0; i < 100000; i++)
	{
		mtx2.lock();
		num2++;
		mtx2.unlock();
	}
}


int main()
{
	
	//创建10个进程并调用函数increase1,每个进程让全局变量num1++100000次
	thread t1(increase1);
	thread t2(increase1);
	thread t3(increase1);
	thread t4(increase1);
	thread t5(increase1);
	thread t6(increase1);
	thread t7(increase1);
	thread t8(increase1);
	thread t9(increase1);
	thread t10(increase1);

	//等待这10个线程执行完,不然下方的输出会提前输出num1=。。。
	t1.join();
	t2.join();
	t3.join();
	t4.join();
	t5.join(); 
	t6.join();
	t7.join(); 
	t8.join();
	t9.join();
	t10.join();

	cout << "预期结果小于100万,未加锁num1=" << num1 << endl;
	/*预期结果小于100万,因为num1++不是原子操作,
	 线程运行到一半会被其他线程抢占cpu导致++没做完
	 */

	//创建10个进程并调用函数increase2,每个进程让全局变量num2++100000次
	thread t11(increase2);
	thread t12(increase2);
	thread t13(increase2);
	thread t14(increase2);
	thread t15(increase2);
	thread t16(increase2);
	thread t17(increase2);
	thread t18(increase2);
	thread t19(increase2);
	thread t20(increase2);
    //等待这10个线程执行完,不然下方的输出会提前输出num2=。。。
	t11.join();
	t12.join();
	t13.join();
	t14.join();
	t15.join();
	t16.join();
	t17.join();
	t18.join();
	t19.join();
	t20.join();
	cout << "预期结果100万,加锁num2=" << num2 << endl;
	//预期结果100万,由于加了锁,num2++不会被中断

	system("pause");
	return 0;
}

运行结果

 创建线程也可以用线程数组

#include<iostream>
#include<thread>
using namespace std;
int n = 0;

void increase() //n累加1000万次
{
	for (int i = 0; i < 10000000; i++)
	{
		n++;
	}

}

int main()
{
	//创建一个有10个元素的线程数组
	thread my_thread[10];

	//启动10个线程,让每个线程调用increase函数
	for (int i = 0; i < 10; i++)
	{
		my_thread[i]=thread(increase);
	}

	//等待这10个线程执行完
	for (int i = 0; i < 10; i++)
	{
		my_thread[i].join();
	}
	//结果会小于1亿
	cout << "全局变量n=" << n << endl;

	system("pause");
	return 0;
}

运行结果(每次都可能不一样)

 

同样的,也可以给n++加互斥锁,这样预期结果就会是1亿


http://www.niftyadmin.cn/n/5667800.html

相关文章

jQuery 简介 ③ ready()事件函数、jQuery 二个原则及容错机制

文章目录 jQuery 简介 ③五、ready() 准备就绪时执行代码六、jQuery 核心1、Get and Set in One 原则2、Get first Set all 原则3、容错机制:jQuery 简介 ③ 五、ready() 准备就绪时执行代码 如果我们在中引入jQuery库文件,并编写相应的jQuery代码来操作DOM元素。这很可能导…

24.9.18学习笔记

序列模型是一种专门用于处理序列数据的机器学习模型。序列数据的特点是其中的数据点之间存在明确的顺序关系或依赖性。这种类型的模型在诸如自然语言处理&#xff08;NLP&#xff09;、语音识别、时间序列预测等领域有着广泛的应用。下面我将详细介绍几种常见的序列模型及其工作…

旋转矩阵乘法,自动驾驶中的点及坐标系变换推导

目录 1. 矩阵乘法的内项相消 2. 左右乘&#xff0c;内外旋与动静坐标系 3. 点变换 3.1 点旋转后的点坐标表示 3.2 坐标系旋转后的点坐标表示 4. 坐标变换的实质 1. 矩阵乘法的内项相消 关于旋转变换&#xff0c;离不开矩阵的乘法&#xff0c;而矩阵乘法的物理意义和本身数…

SpringBoot v2.6.13 整合 swagger

在Spring Boot 2.6.13中整合Swagger需要以下步骤&#xff1a; 添加Swagger依赖到pom.xml&#xff1a; <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version> </d…

嵌入式Linux学习笔记(6)-线程处理、线程同步、线程池(c语言实现)

一、概述 线程是一种轻量级的并发执行的机制。线程是进程中的一个实体&#xff0c;它执行在同一进程的上下文中&#xff0c;共享同一内存空间&#xff0c;但拥有独立的栈空间。 C语言的线程使用pthread库实现&#xff0c;通过包含头文件 pthread.h 来使用相关的函数和数据类型 …

【快速笔记】freeRTOS

第十八章 低功耗Tickless模式 睡眠模式:__WFI 中断唤醒 __WFE 事件唤醒 CPU CLK关闭 停止模式&#xff1a;RAM保持 中断唤醒 当 STM32F103 处于休眠模式的时候 Cortex-M3 内核停止运行&#xff0c;但是其他外设运行正常&#xff0c; 比如 NVIC、SRAM 等。 休眠模式的功耗比其他…

防火墙配置变更管理

在任何组织中&#xff0c;当涉及到网络安全时&#xff0c;频繁地更换防火墙是必要的&#xff0c;实施简化的防火墙更改管理策略模板可以减少管理时间&#xff0c;还可以减少每次变更引入新的安全性或合规性问题的可能性。典型的防火墙变更管理流程将包括以下步骤&#xff1a; …

(一)面试需要掌握的技巧

本系列文章搜集了近几年各类大厂和常见的主流开试题,函给了前端、后端、算法、运维、中间件五大类。希望能给奋斗中的小伙伴们带来或多或少的帮助。 面试不仅仅是我们迈入职业生涯的台阶,它也是个人综合实力的表现,想在心仪的企业有一席之地,有实力才是硬道理。 如何在短…