两个线程同步执行:解决乱箭穿心(STL/Windows/Linux)

news2025/1/19 20:27:25

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;
}

不再乱箭穿心,总是先打印1,后打印2

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;
}

不再乱箭穿心,总是先打印1,后打印2

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

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

相关文章

UART串口Shell软硬件模型分析总结

文章目录 层次一、最底层逻辑配置交互----如何从Uart硬件读写单个字节数据层次二、抽象串口软件模块交互----基于串口对接输入输出流 和 Printf适配层次三、类似Shell封装抽象交互----基于串口交互命令行界面&#xff08;命令解析、补全、修改、记录&#xff09;case1 依次输入…

自建音乐服务器Navidrome之一

这里写自定义目录标题 1.1 官方网站 2. Navidrome 简介2.1 简介2.2 特性 3. 准备工作4. 视频教程5. 界面演示5.1 初始化页5.2 专辑页 前言 之前给大家介绍过 Koel 音频流服务&#xff0c;就是为了解决大家的这个问题&#xff1a;下载下来的音乐&#xff0c;只能在本机欣赏&…

上海的正西边有哪些城市

背景 上海一路向西&#xff0c;来一趟拉萨之行&#xff0c;那么上海出现&#xff0c;所经过的那么多城市&#xff0c;哪些是在上海的正西边呢&#xff1f; 画一幅地图 基于这个背景需求&#xff0c;我们需要拿来一幅地图&#xff0c;一看便知。下面的python代码生成了一幅地…

通信原理板块——平稳随机过程

微信公众号上线&#xff0c;搜索公众号小灰灰的FPGA,关注可获取相关源码&#xff0c;定期更新有关FPGA的项目以及开源项目源码&#xff0c;包括但不限于各类检测芯片驱动、低速接口驱动、高速接口驱动、数据信号处理、图像处理以及AXI总线等 1、平稳随机过程的定义 (1)严平稳随…

UE4 显示遮挡物体

SceneDepth是你相机能够看见的物体的深度距离 CustomDepth是你相机包括看不见被遮挡的物体的深度距离 如果CustemDepth比SceneDepth的距离相等&#xff0c;那么就是没有被遮挡的物体&#xff0c;如果被遮挡那么就是CustemDepth比SceneDepth深度距离远&#xff0c;然后再做对应…

PYTHON知识点学习-循环语句

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是Aileen★。希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f194;本文由 Aileen_0v0★ 原创 CSDN首发&#x1f412; 如需转载还…

【机器学习】线性回归

Model Representation 1、问题描述2、表示说明3、数据绘图4、模型函数5、预测总结附录 1、问题描述 一套 1000 平方英尺 (sqft) 的房屋售价为300,000美元&#xff0c;一套 2000 平方英尺的房屋售价为500,000美元。这两点将构成我们的数据或训练集。面积单位为 1000 平方英尺&a…

Swift 如何从图片数据(Data)检测原图片类型?

功能需求 如果我们之前把图片对应的数据(Data)保持在内存或数据库中,那么怎么从 Data 对象检测出原来图片的类型呢? 如上图所示:我们将 11 张不同类型的图片转换为 Data 数据,然后从 Data 对象正确检测出了原图片类型。 目前,我们的代码可以检测出 jpeg(jpg), tiff,…

WebRTC 安全之一

WebRTC 的安全需要满足三个基本需求 Authentication 用户访问需要认证Authorization 用户访问需要授权Audit 用户的访问应该可被追踪和审查 其中前两项也可以归结为 CIA Confidentiality 机密性&#xff1a;信息需要保密&#xff0c; 访问权限也需要控制Integrity 完整性&#…

Spring Cloud集成Nacos配置中心/注册中心

Spring Cloud版本 2021.0.5 Spring Cloud Alibaba版本 2021.0.5.0 Spring Boot版本 2.7.10 pom文件 需要放在依赖管理的pom文件 <dependencyManagement><dependencies><!-- spring boot依赖 --><dependency><groupId>org.springframewor…

2023-9-3 试除法判定质数

题目链接&#xff1a;试除法判定质数 #include <iostream>using namespace std;bool is_prime(int n) {if(n < 2) return false;for(int i 2; i < n / i; i){if(n % i 0) return false;}return true; }int main() {int n;cin >> n;while(n--){int x;cin &g…

git大文件推送报错

报错信息 不多掰扯&#xff0c;直接上报错信息和截图 Delta compression using up to 8 threadsRPC failde; HTTP 413 curl 22 The requested URL returned error: 413 Request Entity Too Large从以上的报错信息不难看出推送仓库的时候&#xff0c;请求体过大&#xff0c;为…

C++ do...while 循环

不像 for 和 while 循环&#xff0c;它们是在循环头部测试循环条件。do…while 循环是在循环的尾部检查它的条件。 do…while 循环与 while 循环类似&#xff0c;但是 do…while 循环会确保至少执行一次循环。 语法 C 中 do…while 循环的语法&#xff1a; do {statement(s…

AD16 基础应用技巧(一些 “偏好“ 设置)

1. 修改铺铜后自动更新铺铜 AD16 铺铜 复制 自动变形 偏好设置 将【DXP】中的【参数选择】。 将【PCB Editor】中的【General】&#xff0c;然后勾选上【Repour Polygons After Modification】。 2. PCB直角走线处理与T型滴泪 一些没用的AD技巧——AD PCB直角走线处理与…

iOS练手项目知识点汇总

基础理解篇 Objective-C是一种面向对象的编程语言&#xff0c;它支持元编程。元编程是指编写程序来生成或操纵其他程序的技术。 Objective-C中&#xff0c;元编程可以使用Objective-C的动态特性来实现。例如可以使用Objective-C的运行时函数来动态地创建类、添加属性和方法等等…

给视频添加背景图片,让它们更具魅力!

想要让你的视频更加出彩吗&#xff1f;给它们添加背景图片是不错的选择&#xff01;但是&#xff0c;如何做到呢&#xff1f;不用担心&#xff0c;我们的视频剪辑高手可以帮助你轻松实现&#xff01;我们提供多种背景图片选择&#xff0c;你可以根据自己的喜好和需求进行选择。…

程序员自由创业周记#7:仲裁

没想到 没想到写的周记会有这么多人看&#xff0c;还能收到这么多陌生(或熟悉)朋友的真诚建议、鼓励、甚至是打赏&#xff0c;几乎所有的评论和私信我都认真的回复了&#xff0c;本想的是通过网友和朋友的监督坚定我创业的信念&#xff0c;有点外界压力也能迫使自己持续输出一…

P1886 滑动窗口 /【模板】(双端队列)+双端队列用法

例题 有一个长为 n 的序列 a&#xff0c;以及一个大小为 k 的窗口。现在这个从左边开始向右滑动&#xff0c;每次滑动一个单位&#xff0c;求出每次滑动后窗口中的最大值和最小值。 例如&#xff1a; The array is [1,3,−1,−3,5,3,6,7],and k3。 输入格式 输入一共有两行…

4. 虚拟机栈

4.1. 虚拟机栈概述 4.1.1. 虚拟机栈出现的背景 由于跨平台性的设计&#xff0c;Java的指令都是根据栈来设计的。不同平台CPU架构不同&#xff0c;所以不能设计为基于寄存器的。 优点是跨平台&#xff0c;指令集小&#xff0c;编译器容易实现&#xff0c;缺点是性能下降&…

WideDeep模型介绍

文章目录 1. Wide&Deep模型的记忆能力和泛化能力2. Wide&Deep模型的结构3. Wide&Deep模型的进化——Deep&Cross模型4. Wide&Deep模型的影响力 Wide&Deep模型是 记忆能力和 泛化能力的综合&#xff0c;是谷歌在2016年提出的。正如其名&#xff0c;Wid…