两个线程同步执行:解决乱箭穿心(STL/Windows/Linux)
C++自学精简教程 目录(必读)
C++并发编程入门 目录
多线程同步
线程之间同步是指线程等待其他线程执行完某个动作之后再执行(本文情况)。
线程同步还可以是像十字路口的红绿灯一样,只允许一个方向的车同行,其他方向的车等待。
本文将使用信号量来实现线程同步。
一个线程通知另一个线程,另一个线程等待被通知信号。
一个发送线程先往控制台上打印1,这时候接收线程并不往控制台打印2,而是等待发送线程发给自己的信号,等到信号之后再打印2.
每次发送线程打印完自己的数据之后,睡眠1毫秒,给接收线程时间来完成自己的工作。
睡眠1毫秒合理吗?
这里睡眠1毫秒是合理的。
多个线程在协调工作的时候,每个线程都会需要时间来才能解决问题。
所以作为协调源头的线程1,应该给其他线程时间来处理问题,这是合理的。
例如,在音视频开发中,采集是源头,比如120HZ的视频,时间间隔是8.333ms,所有后续的编码线程,推流线程,等等,都需要在这有限的8.333毫秒之内完成自己的工作。
STL 写法
// condition_variable::notify_one
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable
#include <chrono> //milliseconds
using namespace std;
using namespace chrono;std::mutex mutex1;
std::condition_variable event;void thread_sender_fun(void)
{while (true){cout << "1";event.notify_one();this_thread::sleep_for(milliseconds(1));}
}void thread_receiver_fun()
{while (true){std::unique_lock<std::mutex> lock(mutex1);event.wait(lock);cout << "2";}
}int main()
{std::thread thread_sender(thread_sender_fun);std::thread thread_receiver(thread_receiver_fun);// join them back:thread_sender.join();thread_receiver.join();return 0;
}

Windows 写法
#include <windows.h>
#include <iostream>
using namespace std;HANDLE event;//事件对象DWORD WINAPI sender_event_thread_fun(LPVOID lpParam)
{while (true){cout << "1";//干活SetEvent(event);//发出写完成信号,通知另一个线程该打印2了Sleep(1);}return 0;
}DWORD WINAPI receive_event_thread_fun(LPVOID lpParam)
{UNREFERENCED_PARAMETER(lpParam);while (true){DWORD dwWaitResult = WaitForSingleObject(event, INFINITE);// 等待信号,无限等待cout << "2";//干活}return 0;
}int main(void)
{event = CreateEvent(NULL,//是否需要人工ResetEvent重置为无信号状态://是:当该事件为有信号状态时,所有等待该信号的线程都变为可调度线程。// 并且,需要手动调用ResetEvent为无信号状态;//否:当该事件为有信号状态时,只有一个线程变为可调度线程。// 并且,系统自动调用ResetEvent将该对象设置为无信号状态。(一次性的信号)FALSE,FALSE,//初始状态:无信号状态TEXT("WriteFinishedEvent")// 事件对象名称);//创建线程HANDLE thread_sender = CreateThread(NULL, 0, sender_event_thread_fun, NULL, 0, NULL);HANDLE thread_receive = CreateThread(NULL, 0, receive_event_thread_fun, NULL, 0, NULL);HANDLE handleArr[] = { thread_sender , thread_receive };//等待线程执行结束WaitForMultipleObjects(2, handleArr, TRUE, INFINITE);//释放资源CloseHandle(thread_sender);CloseHandle(thread_receive);CloseHandle(event);return 0;
}
Linux 写法
#include <pthread.h>
#include <semaphore.h>
#include <iostream>
#include <unistd.h>//usleep
using namespace std;sem_t event;void* thread_sender_fun(void* arg)
{while (true){cout << "1";sem_post(&event);usleep(1000);//休眠一毫秒}return 0;
}void* thread_receive_fun(void* arg)
{while (true){sem_wait(&event);cout << "2";}return 0;
}int main(int argc, char *argv[])
{pthread_t thread_sender;pthread_t thread_receiver;sem_init(&event, 0, 0);pthread_create(&thread_sender, NULL, thread_sender_fun, NULL);pthread_create(&thread_receiver, NULL, thread_receive_fun, NULL);pthread_join(thread_sender, NULL);pthread_join(thread_receiver, NULL);return 0;
}
相关文章:
两个线程同步执行:解决乱箭穿心(STL/Windows/Linux)
C自学精简教程 目录(必读) C并发编程入门 目录 多线程同步 线程之间同步是指线程等待其他线程执行完某个动作之后再执行(本文情况)。 线程同步还可以是像十字路口的红绿灯一样,只允许一个方向的车同行,其他方向的车等待。 本…...
Ubuntu18.04更改镜像源(网易,阿里,清华,中科大,浙大)
一,备份原来的源(选做) sudo cp /etc/apt/sources.list /etc/apt/sources_init.list 二,更换源 sudo gedit /etc/apt/sources.list 删除原来内容改为新的镜像源 1,清华源 deb https://mirrors.tuna.tsinghua.edu…...
字节码和机器码的区别
字节码和机器码是计算机程序在不同阶段的表示形式,它们的主要区别如下: 抽象级别不同:字节码是一种中间表示形式,位于源代码和机器码之间。它是一种与特定平台无关的低级表示形式,通常由编译器将源代码转换而来。而机器…...
go学习part21 Redis和Go(2)
1.三方库安装 309_尚硅谷_Go连接到Redis_哔哩哔哩_bilibili 借鉴: Golang 安装 Redis_go fiber 安装redis_柒柒伍贰玖。的博客-CSDN博客 三方redis库已经迁移到以下网址,go get github.com/gomodule/redigo/redis gomodule/redigo: Go client for Red…...
从0到1学会Git(第二部分):Git的本地操作和管理
写在前面:本文介绍了在本地仓库进行文件的处理以及本地的合并等操作。 前置知识:文件可以处在三个区域,分别为工作区,暂存区和本地仓库,我们此文的目标即是将文件存储在本地仓库中。我们可以将文件的区域理解为,cpu中,…...
hive lateral view 实践记录(Array和Map数据类型)
目录 一、Array 1.建表并插入数据 2.lateral view explode 二、Map 1、建表并插入数据 2、lateral view explode() 3、查询数据 一、Array 1.建表并插入数据 正确插入数据: create table tmp.test_lateral_view_movie_230829(movie string,category array&…...
理解 std::thread::join
C多线程并发编程入门(目录) 本文用最简单易懂的实际案例,讲清楚了 join 的实际内涵,保证你过目不忘。 Hello join 示例 join 函数是我们接触C多线程 thread 遇到的第一个函数。 比如: int main() {thread t(f);t.…...
C#循环定时上传数据,失败重传解决方案,数据库标识
有些时候我们需要定时的上传一些数据库的数据,在数据不完整的情况下可能上传失败,上传失败后我们需要定时在重新上传失败的数据,该怎么合理的制定解决方案呢?下面一起看一下: 当然本篇文章只是提供一个思路࿰…...
R语言图形的组合( par(),layout(),par(fig()) )
引入d.class进行画图 > d.class<-read.csv("D://class.csv",header T) > attach(d.class) > opar<-par(no.readonly TRUE)非常简单的数据,需要可自取 链接:https://pan.baidu.com/s/1zNx5z9JsaaRqFueRgGY3mQ 提取码&#x…...
如何为 Flutter 应用程序创建环境变量
我们为什么需要环境变量? 主要用于存储高级机密数据,如果泄露可能会危及您产品的安全性。这些变量本地存储在每个用户的本地系统中,不应该签入存储库。每个用户都有这些变量的副本。 配置 在根项目中创建一个名为 .env 的文件夹(…...
「C++程序设计 (面向对象进阶)」学习笔记・一
0、引言 本专栏的系列文章是在学习 北京邮电大学 崔毅东 老师的《C程序设计 (面向对象进阶)》课程过程中整理的。欢迎前往专栏了解更多相关内容~ 😀 有关于现代 C 的基本介绍,请前往《现代C基本介绍》! 🔔 先决条件 本专栏的系列…...
Leetcode125. 验证回文串
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。 字母和数字都属于字母数字字符。 给你一个字符串 s&…...
【Yellowbrick】特征可视化分析
Yellowbrick特征可视化分析 ⭐Yellowbrick⭐特征分析可视化⭐Rank1D⭐Rank2D ⭐Yellowbrick Yellowbrick是一个用于可视化机器学习模型和评估性能的Python库。它提供了一系列高级可视化工具,帮助数据科学家和机器学习从业者更好地理解、调试和优化他们的模型。 它在…...
Android大厂需要刷的(999道)面试题
想必大家都在为今年的金九银十做准备,今年也是最为艰难的一年。作为程序员从未感觉到如此艰难,身边不是被辞退就是找不到工作。先不说2023年应届生毕业即失业,作为开发15年的老Android程序员,现在也在和300个人挣一个岗位。 肉少…...
Pycharm中出现ImportError:DLL load failed:找不到指定模块的解决方法
不论搭建什么工程,运行什么文件,只要在Pycharm中出现ImportError: DLL load failed: 找不到指定的模块这样的问题,以下方法都适用!!! 一、问题描述 我在使用pycharm连接webots,用python控制机…...
Java设计模式:四、行为型模式-08:策略模式
文章目录 一、定义:策略模式二、模拟场景:策略模式三、违背方案:策略模式3.0 引入依赖3.1 工程结构3.2 优惠券折扣计算类3.3 单元测试 四、改善代码:策略模式4.1 工程结构4.2 策略模式结构图4.3 优惠券折扣实现4.3.1 定义优惠券接…...
ICCOA蓝牙数字车钥匙2.0
近期,ICCOA智慧车联开放联盟宣布,由小米、vivo、OPPO、长安、深蓝、吉利、极氪、比亚迪、北汽、蔚来、零跑、雪球、瓶钵、融卡等企业联合参与制定的ICCOA蓝牙数字车钥匙2.0标准(简称DK2.0),于2023年9月1日正式发布实施…...
ArcGIS土地利用程度综合指数分析
成图展示: 土地利用程度综合指数 第一步 准备数据 使用的数据为2010年河南省土地利用类型数据与其行政区划县级数据(为了节省操作,这里使用上次实验的部分数据[1],各土地利用类型已被提取) 第二步 面积统计 水域为例…...
服务端请求伪造(SSRF)及漏洞复现
文章目录 渗透测试漏洞原理服务端请求伪造1. SSRF 概述1.1 SSRF 场景1.1.1 PHP 实现 1.2 SSRF 原理1.3 SSRF 危害 2. SSRF 攻防2.1 SSRF 利用2.1.1 文件访问2.1.2 端口扫描2.1.3 读取本地文件2.1.4 内网应用指纹识别2.1.5 攻击内网Web应用 2.2 SSRF 经典案例2.2.1 访问页面2.2.…...
v-model和v-bind
v-model,它其实就是一个语法糖,作用就是双向绑定表单控件(radio, text,address,email,select,checkbox,textarea) v-bind(简写形式:value值),用于绑定属性值,只能实现数据的单项绑定。 <template> <div>…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...
wpf在image控件上快速显示内存图像
wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像(比如分辨率3000*3000的图像)的办法,尤其是想把内存中的裸数据(只有图像的数据,不包…...
【Veristand】Veristand环境安装教程-Linux RT / Windows
首先声明,此教程是针对Simulink编译模型并导入Veristand中编写的,同时需要注意的是老用户编译可能用的是Veristand Model Framework,那个是历史版本,且NI不会再维护,新版本编译支持为VeriStand Model Generation Suppo…...
C++--string的模拟实现
一,引言 string的模拟实现是只对string对象中给的主要功能经行模拟实现,其目的是加强对string的底层了解,以便于在以后的学习或者工作中更加熟练的使用string。本文中的代码仅供参考并不唯一。 二,默认成员函数 string主要有三个成员变量,…...
如何把工业通信协议转换成http websocket
1.现状 工业通信协议多数工作在边缘设备上,比如:PLC、IOT盒子等。上层业务系统需要根据不同的工业协议做对应开发,当设备上用的是modbus从站时,采集设备数据需要开发modbus主站;当设备上用的是西门子PN协议时…...
高端性能封装正在突破性能壁垒,其芯片集成技术助力人工智能革命。
2024 年,高端封装市场规模为 80 亿美元,预计到 2030 年将超过 280 亿美元,2024-2030 年复合年增长率为 23%。 细分到各个终端市场,最大的高端性能封装市场是“电信和基础设施”,2024 年该市场创造了超过 67% 的收入。…...
