线程并发同步--条件变量--conditional_variable

news2024/11/25 2:20:37

        同步:我的线程完成之后,你在进行下一个线程。可以理解为进货和卖货,即只有进或的线程结束后才可以执行卖货的这个线程。

        c++中提供了一个工具:conditional_variable。实现有两种方式,一种是condition_variable和conditon_variable_any。这里种方式使用时要配合互斥量使用,前者配合mutex。后者配合的多西只要能充当互斥就可以了。后者更加灵活。但是额外的开销也更大。

        这个condition_variable除了构造函数之外,wait这一函数也很重要。用于等待信号,既然有等待信号,那么也一定有发出信号,其函数为  notify_one  和  notify_all  。前者通知某一个线程,后者通知所有线程。

例程如下:线程1控制线程2,线程1修改一个值,修改完之后线程2才可以继续执行。

#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<Windows.h>

using namespace std;

mutex mtx;
condition_variable flag;


void thread1(void);
void thread2(void);
int c = -1;
int main(void)
{
	thread t1(thread1);
	thread t2(thread2);

	t1.join();
	t2.join();

	return 0;
}

void thread1(void)//线程1的作用是修改全局变量,然后线程2才可以运行
{
	int i = 0;
	Sleep(5000);
	while (1)
	{
		{
			lock_guard<mutex> lck(mtx);
			c = i++;
		}//花括号的作用是创建代码块
		//一个代码块结束之后就会自动释放里面的类
		//一旦释放了类就会自动调用析构函数解锁
		flag.notify_one();
		Sleep(1000);
	}
}

void thread2(void)
{
	while (1)
	{
		unique_lock<mutex> lck(mtx);
		//lock_guard这个模板是无法暂时性的释放锁的,所以这里不用lock_guard
		cout << "Thread2 waits for count: " << endl;
		flag.wait(lck);//wait在等待接受信号的同时还有一个作用就是暂时性的解锁
		cout << c << endl;
	}
}

运行结果如下:

         显然,大家看来了上面的代码必定是一头雾水,下面本文将从头刨析一次thread1和thread2:

第一步:

        显然因为线程1睡了5秒,是线程2霸占了玩具A, 但是线程2在霸占玩具A之后要等待信号A才能继续往下走,但是信号A由线程1发出,线程1只有霸占了玩具A才能发处信号A,显然,此时线程1无法霸占玩具A,因为其已经被线程2霸占了。

        如果线程2能在等待信号A的同时解除对玩具A的霸占就好了:此时就是flag.wait()有这个功能,可以在等待的同时解除霸占。如下:

 注意flag.wait()必须配合unique_lock()才能实现。

此时线程2解除了对玩具A的霸占,玩具A由线程1霸占:

        当线程2的while循环内第一次运行结束之后,开始进行第二次时,他想要霸占玩具A,但此时玩具A被线程1霸占 ,线程2无法进入第76行等待,也就无法进行下去了。

        那么此时就需要线程1把玩具A的霸占解除才行:使用代码段的方式:

        如上:加了一个花括号(63行,66行),在花括号里面的内容执行完后,自动释放花括号里面的数据,就把类给释放了,释放的同时调用了析构函数,就解锁即解除霸占。 

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

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

相关文章

[java]Redis

关于Redis Redis是一款基于内存的&#xff0c;使用K-V结构存储数据的NoSQL非关系型数据库。 基于内存的&#xff1a;Redis读写数据时&#xff0c;都是在内存中进行读写的&#xff0c;所以&#xff0c;读写效率非常高&#xff01;另外&#xff0c;Redis会自动的将所管理的数据同…

mmdetection自定义数据集训练

目录 1. 源码下载&#xff0c;本文基于v3.0版本 2.选模型训练 2.1 先生成后面用于编译的配置文件 2.2.1 修改coco.py 2.2.2 修改class_names.py 3. 训练配置 4. 训练过程展示 1. 源码下载&#xff0c;本文基于v3.0版本 GitHub - open-mmlab/mmdetection: OpenMMLab Detec…

UART-GD32

UART-GD32 通信的概念 同步通信和异步通信 数据帧格式 波特率 使用步骤 引脚分布

图-深度优先搜索与广度优先搜索

图 在现实生活中&#xff0c;有许多应用场景会包含很多点以及点点之间的连接&#xff0c;而这些应用场景我们都可以用即将要学习的图 这种数据结构去解决 地图 我们生活中经常使用的地图&#xff0c;基本上是由城市以及连接城市的道路组成&#xff0c;如果我们把城市看做是一…

西安石油大学 C++期末考试 重点知识点+题目复习(上)

第一章 “const”关键字的用法 当使用 const 修饰变量、函数参数、成员函数以及指针时&#xff0c;以下是一些代码示例&#xff1a; 声明只读变量&#xff1a; const int MAX_VALUE 100; const float PI 3.14;保护函数参数&#xff1a; void printArray(const int arr[]…

解决vmware虚拟机,克隆修改ip后,xshell连接不上问题

1、查看网卡 ifconfig2、修改网卡配置 vim /etc/sysconfig/network-scripts/ifcfg-ens32 改成与上图一样 修改后 3、重启reboot则解决

STM32F407 串口配置步骤

介绍STM32F407串口配置步骤&#xff0c;完成串口的数据发送与接收、实现中断接收&#xff0c;支持printf重定向。 STM32F407 串口配置说明 STM32F4 的串口资源相当丰富的&#xff0c;功能也相当强劲&#xff0c;STM32F407ZGT6 最多可提供 6 路串口&#xff0c;有分数波特率发…

【Junit 单元测试】

Junit 单元测试 笔记记录 1. Junit介绍2. 使用Junit3. 常用注解4. 断言使用 1. Junit介绍 2. 使用Junit 1.导入依赖 <dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>tes…

C语言-基础语法学习-4 字符串

目录 字符串C语言字符串及相关函数定义字符数组和字符串的区别sizeof()和strlen()的区别动态开辟字符串野指针常用字符串函数 字符串 C语言字符串及相关函数 在C语言中&#xff0c;字符串是由字符数组表示的一系列字符序列。C语言提供了一些函数来处理字符串&#xff0c;使我…

centos磁盘扩容

解释 PE - 物理块&#xff08;Physical Extent&#xff09; 硬盘上有很多实际物理存在的存储块PV - 物理卷 &#xff08;Physical Volume&#xff09; 物理卷处于最底层&#xff0c;它可以是实际物理硬盘上的分区&#xff0c;也可以是整个物理硬盘(相当于单独做一个分区)&…

CommonJS 和 ES6 module

本文主要自己觉得要记录的点记录下来,不耽误大家时间&#xff0c;会持续更新。 Module对象 Module {id: xxx/demo/1.js, //加载文件的绝对路径path: xxx/demo,// 加载文件所在目录的绝对路径exports: [Function (anonymous)],filename: xxx/demo/1.js,加载文件的绝对路径load…

B/S和C/S详解(嵌入式学习)

B/S和C/S详解 1. C/S1.1 概念1.2 C/S架构的特点 2. B/S2.1 概念2.2 B/S架构的特点2.3 相对于传统的C/S架构的优势 3. B/S架构详解4. B/S架构怎么用&#xff08;CGI、Lighttpd&#xff09; 1. C/S 1.1 概念 C/S&#xff08;Client/Server&#xff09;是一种计算机网络架构模式…

【C++】 Qt-页面布局

文章目录 布局组件和布局按钮练习-用户信息页面布局准备工作设置性别设置年龄设置生日设置邮箱后缀 设置头像创建文件写入文件清空表单信息Buddy&#xff08;伙伴&#xff09;关系Tab顺序 布局组件和布局按钮 Qt的UI设计器中提供了丰富的布局管理功能&#xff0c;组件面板里有…

高效简单解决滑动验证码

前言 做爬虫总会遇到各种各样的反爬限制&#xff0c;其中移动验证码是很重要且常见的一环&#xff0c;今天总结下如何高效破解他的方法&#xff0c;例如下图&#xff1a; 解决思路与方法 首先先来分析下&#xff0c;核心问题其实是要怎么样找到目标缺口的位置&#xff0c;一…

Windows服务启动exe无界面终极解决方案

1、前言 我这个方案&#xff08;C#操作&#xff09;是彻底解决【从Windows服务启动程序exe&#xff0c;程序无界面】问题的终极解决方案&#xff0c;终极方案&#xff0c;绝对的终极方案&#xff0c;本来打算收钱的&#xff0c;还是算了&#xff0c;你们也不容易&#xff0c;关…

网络安全(自学笔记)

如果你真的想通过自学的方式入门web安全的话&#xff0c;那建议你看看下面这个学习路线图&#xff0c;具体到每个知识点学多久&#xff0c;怎么学&#xff0c;自学时间共计半年左右&#xff0c;亲测有效&#xff08;文末有惊喜&#xff09;&#xff1a; 1、Web安全相关概念&am…

Redis 性能管理/优化 缓存雪崩/击穿/穿透

---------------------- Redis 性能管理 ---------------------------------------- ----- 查看Redis内存使用 ----- info memoryredis-cli -a abc123 info memory ----- 内存碎片率 ----- used_memory_rss&#xff1a;是Redis向操作系统申请的内存。used_memory&#xff1a;是…

缺失concrt140.dll下载,找不到concrt140.dll的解决方法

我们平时在打开 Adobe 应用程序、Halo、Forza Horizon 5 等时&#xff0c;可能会遇到找不到 concrt140.dll。因此&#xff0c;这不是特定于某个应用程序的问题。如果没有安装正确的 DLL&#xff0c;应用程序将无法正常工作&#xff0c;因为它们的代码依赖于这些库中编写的代码。…

井盖异动监测传感器:井盖的安全守护者

随着城市化进程的不断加速&#xff0c;城市道路、人行道上的井盖扮演着重要的角色。然而&#xff0c;由于各种因素&#xff0c;如车辆冲击、材料老化等&#xff0c;井盖常常会出现异动情况&#xff0c;井盖异动不仅对行车和行人的安全构成威胁&#xff0c;还给城市基础设施的维…

C#扩展——Visual Studio 代码提示/智能提示字体大小更改方法.

声明&#xff1a;本文为个人笔记&#xff0c;用于学习研究使用非商用&#xff0c;内容为个人研究及综合整理所得&#xff0c;若有违规&#xff0c;请联系&#xff0c;违规必改。 C#扩展——Visual Studio 代码提示/智能提示字体大小更改方法. 文章目录 C#扩展——Visual Studio…