C++中关于多线程同步问题

C++线程同步——阻塞线程的方法 C头文件 <semaphore.h>中 sem_wait() 会阻塞当前线程 sem_trywait() 返回错误而不是阻塞调用 sem_timedwait() sem_timedwait的abs_timeout参数指定了调用应该阻塞的时间限制 信号量 信号量 (semaphore) 是一种轻量的同步原件,用于制约对共享资源的并发访问。在可以使用两者时,信号量能比条件变量更有效率。 定义于头文件 <semaphore> counting_semaphore 实现非负资源计数的信号 阅读详情

题目:

我们提供了一个类:

public class Foo {
  public void one() { print("one"); }
  public void two() { print("two"); }
  public void three() { print("three"); }
}
三个不同的线程将会共用一个 Foo 实例。

线程 A 将会调用 one() 方法
线程 B 将会调用 two() 方法
线程 C 将会调用 three() 方法
请设计修改程序,以确保 two() 方法在 one() 方法之后被执行,three() 方法在 two() 方法之后被执行。

 

1.  利用Mutex实现:

      mutex一般用于为一段代码加锁,以保证这段代码的原子性(atomic)操作,即:要么不执行这段代码,要么将这段代码全部执行完毕。mutex主要用于互斥情况,适用于同步。

#include<mutex>
class Foo {
public:
    Foo() {
         m1.lock();m2.lock();
    }

    void first(function<void()> printFirst) {
        
        // printFirst() outputs "first". Do not change or remove this line.
        printFirst();
        m1.unlock();
    }

    void second(function<void()> printSecond) {
        
        // printSecond() outputs "second". Do not change or remove this line.
        m1.lock();
        printSecond();
        m1.unlock();
        m2.unlock();
    }

    void third(function<void()> printThird) {
        
        // printThird() outputs "third". Do not change or remove this line.
        m2.lock();
        printThird();
        m2.unlock();
    }
private:
    std::mutex m1,m2;
    
};

2. 使用信号量semaphore实现

semaphore可以实现资源的限额使用,既可以用于同步的互斥,也可以用于并行多任务。

信号量本质上是一个计数器(不设置全局变量是因为进程间是相互独立的,而这不一定能看到,看到也不能保证++引用计数为原子操作),用于多进程对共享数据对象的读取,它和管道有所不同,它不以传送数据为主要目的,它主要是用来保护共享资源(信号量也属于临界资源),使得资源在一个时刻只有一个进程独享。

信号量工作原理:

由于信号量只能进行两种操作等待和发送信号,即P(sv)和V(sv),他们的行为是这样的:

(1)P(sv):如果sv的值大于零,就给它减1;如果它的值为零,就挂起该进程的执行

(2)V(sv):如果有其他进程因等待sv而被挂起,就让它恢复运行,如果没有进程因等待sv而挂起,就给它加1.

二元信号量:与mutex等效

二元信号量(Binary Semaphore)是最简单的一种锁(互斥锁),它只用两种状态:占用与非占用。所以它的引用计数为1。

 

首先看下错误代码:

#include<semaphore.h>
class Foo {
public:
    Foo() {
        sem_init(&mutex_,0,1);
        sem_init(&m,0,1);
        //sem_wait(&mutex_);
        //sem_wait(&m);
    }

    void first(function<void()> printFirst) {
        
        // printFirst() outputs "first". Do not change or remove this line.
        sem_wait(&m);
        sem_wait(&mutex_);
        printFirst();
        sem_post(&mutex_);
        sem_post(&m);
    }

    void second(function<void()> printSecond) {
        
        // printSecond() outputs "second". Do not change or remove this line.
       sem_wait(&m);
        sem_wait(&mutex_);
        printSecond();
         sem_post(&mutex_);
        sem_post(&m);
    }

    void third(function<void()> printThird) {
        
        // printThird() outputs "third". Do not change or remove this line.
       sem_wait(&m);
        sem_wait(&mutex_);
        printThird();
        sem_post(&mutex_);
        sem_post(&m);
    }
private:
    sem_t mutex_,m;
    
};

错误原因是:三个线程/进程同步请求信号量资源m,谁在前面谁先得到,若打乱顺序,得到的线程启动也会随之打乱,如【1,3,2】则会一次执行方法1,3,2,与题意的1,2,3固定次序不符。需要在三个线程请求前,设置PV操作。

正确代码如下:

#include<semaphore.h>
class Foo {
public:
    Foo() {
        sem_init(&mutex_,0,1);
        sem_init(&m,0,1);
        sem_wait(&mutex_);   ////设置wait-P操作, 互斥
        sem_wait(&m);  // 设置wait-P操作,资源量
    }

    void first(function<void()> printFirst) {
        
        // printFirst() outputs "first". Do not change or remove this line.
        // sem_wait(&m); //无需wait-P操作
        // sem_wait(&mutex_);  //无需wait-P操作
        printFirst();
        sem_post(&mutex_);
        //sem_post(&m);
    }

    void second(function<void()> printSecond) {
        
        // printSecond() outputs "second". Do not change or remove this line.
       // sem_wait(&m);
       //  sem_wait(&mutex_);
         sem_wait(&mutex_);
        printSecond();
        sem_post(&m);
    }

    void third(function<void()> printThird) {
        
        // printThird() outputs "third". Do not change or remove this line.
       sem_wait(&m);
        printThird();
        sem_post(&m);
    }
private:
    sem_t mutex_,m;
    
};

3. 使用pthread_mutex_t实现

#include<semaphore.h>
#include <pthread.h>
//pthread_mutexattr_init(pthread_mutexattr_t *mattr);
class Foo {
public:
    Foo() {
        pthread_mutex_init(&pmutx,NULL);
        pthread_mutex_init(&pm,NULL);
        pthread_mutex_lock(&pmutx);
        pthread_mutex_lock(&pm);
    }

    void first(function<void()> printFirst) {
        
        // printFirst() outputs "first". Do not change or remove this line.
        // sem_wait(&m); //无需wait-P操作
        // sem_wait(&mutex_);  //无需wait-P操作
        printFirst();
        pthread_mutex_unlock(&pmutx);
    }

    void second(function<void()> printSecond) {
        
        // printSecond() outputs "second". Do not change or remove this line.
       // sem_wait(&m);
       //  sem_wait(&mutex_);
          pthread_mutex_lock(&pmutx);
        printSecond();
        
         pthread_mutex_unlock(&pm);
    }

    void third(function<void()> printThird) {
        
        // printThird() outputs "third". Do not change or remove this line.
       pthread_mutex_lock(&pm);
        
        printThird();
       
        pthread_mutex_unlock(&pmutx);
    }
private:
    pthread_mutex_t pmutx,pm;
    
};

 

参考文献:https://www.cnblogs.com/wuyepeng/p/9748552.html

C++11 - thread多线程编程,线程互斥和同步通信,死锁问题分析解决 c++11 thread线程库使用,线程互斥,互斥锁,死锁问题分析定位 阅读详情

相关推荐

C++多线程之旅-线程同步问题

目录前言互斥元保护数据互斥元死锁互斥元所有权总结 前言 在前一篇文章中可以实现简单的线程创建,但是会出现一个问题就是,在cout打印输出的时候会出现莫名其妙的乱序。 void fun(){ cout << "this_thread::id = " << this_thread::get_id() << endl; } int main() { vector<thread> vec; for (int i = 0; i < 100;

或许没有的博客 495

C/C++多线程、线程同步(互斥锁与信号量)

参考链接2.中写的非常好,简单易懂,上手快,非常好的博文。使用多线程及互斥锁样例:#include &lt;iostream&gt; #include &lt;windows.h&gt; using namespace std; HANDLE hMutex = NULL;//互斥量 //线程函数 DWORD WINAPI Fun(LPVOID lpParamter) { for (int...

邦戈邦戈栗子的博客 8015

C++多线程编程,线程互斥和同步通信,死锁问题分析解决

c/c++ linux服务器开发相关视频解析: 后台开发第178讲|【零声学院官方视频】epoll原理剖析以及reactor模型应用|1. epoll原理剖析 2. 单reactor原理以及应用 聊聊线程面试那些事||线程起源||线程模型||进程和线程的联系和区别||为什么需要线程池 c/c++ linux服务器开发免费学习地址:c/c++ linux后台服务器高级架构师 C++11的多线程类thread C++11之前,C++库中没有提供和线程相关的类或者接口,因此在编写多线程程..

Linux高级开发的博客 707

C++多线程之共享资源同步

c++ 多线程之共享资源同步 在上一节里面,我们学习了如何通过c++来创建和管理线程, 这一节我们主要学习如何同步多线程中的资源。 什么是同步资源呢?简单来说就是实现多线程共享资源的安全访问,举个例子来说,如果两个线程都需要对同一个变量进行修改,如果不加控制的话,这个变量最后的结果可能就不是我们预期的结果了,大家先来看以下的代码示例: 无线程同步例子 在这里插入代码片 有线程同步的例子 在这里插入代码片 大家可以把上面的例子先拷贝到自己的c++运行环境里面,运行结果对比一下。 大家会发现第一个例

琉璃易冷的博客 1668

手把手教你用Cadence仿真12bit SAR ADC:从电路图到FFT频谱分析(含Simc 18mmrf工艺文件)

本文详细介绍了使用Cadence仿真12bit SAR ADC的全流程,包括电路搭建、仿真环境配置、瞬态仿真优化及FFT频谱分析。基于Simc 18mmrf工艺文件,提供从电路图到性能验证的实战指南,特别分享工程实践中的排错技巧和优化策略,帮助工程师高效完成ADC设计验证。

weixin_30832405的博客 406

DeepSeek API调用太复杂?OneAPI一站式聚合解决方案

本文介绍了OneAPI如何作为一站式聚合解决方案,简化DeepSeek API的调用流程。通过统一接口、智能路由和模型映射等核心功能,OneAPI大幅降低了多API适配的复杂性,提升开发效率。文章还提供了详细的部署指南和高阶使用技巧,帮助开发者快速实现API聚合管理。

weixin_27215337的博客 381

7-149 多线程计算 (20 分)

7-149 多线程计算 (20 分) 已知某学校有n名教师,学校有m名学生,学校搞学生民意调查,每一位学生为每一位老师都打分,学生所打的所有的分数都集中到一个数组中。数据存放规律是,前m个数据是对1号老师的打分,接下来m个数据是对2号老师的打分,以此类推。请设计一个多线程的算法,计算出每一位老师的总打分。 输入格式: 第一行输入教师数,第二行输入学生数,第三行输入所有n*m个打分(整型),各个分数之间以一个空格分隔 输出格式: 按照教师原来的顺序,每行输出每一位老师的得分 输入样例: 在这里给出一组输入。例

qq_54260963的博客 3395

新能源车主必看:用高德API+充电站数据制作跨城出行充电规划工具(附完整代码)

本文为新能源车主提供了一份详细的跨城出行充电规划工具构建指南。通过整合高德地图API与充电站数据,手把手教你使用Python开发一个智能规划系统,可自动规划路线并推荐沿途充电站,有效缓解里程焦虑。文章包含完整代码、核心算法解析及可视化实现,帮助车主实现个性化、高效的出行规划。

tgb3456789的博客 900

多线程基础知识学习总结

多线程基础知识学习总结线程的历史 —— 一部对CPU压榨的血泪史线程进程概念单核CPU设定多线程是否有意义?工作线程数是否设置的越大越好? 线程的历史 —— 一部对CPU压榨的血泪史 1、单线程人工切换(纸带机) CPU利用效率低很多时间是等着人去换各种纸带 2、多进程批处理(多个任务批量执行) 但是如果其中一个任务等待的话也会导致其他任务跟着等待 3、多进程并行处理(把程序写在不同的内存位置上来回切换) 4、多线程(一个程序内部不同任务的来回切换) 5、纤程/协程(绿色线程,用户管理的【而不是OS管理的】

lsd&xql的博客 388

基于多智能体协作的量化交易研究框架TradingAgents详解

量化交易系统通过算法模型分析市场数据,旨在实现自动化投资决策。其核心原理在于利用计算机强大的数据处理能力,结合统计学和机器学习方法,从历史数据中挖掘可重复的盈利模式。这一技术的价值在于能够克服人类情绪干扰,实现纪律性交易,并快速处理海量信息。在应用场景上,量化策略广泛应用于股票、期货、外汇等多个金融市场。本文聚焦的TradingAgents框架,创新性地引入了**多智能体协作**和**对抗性验证**机制,通过模拟真实投研团队的分工与辩论流程,构建了一个研究友好、决策过程可解释的量化交易研究平台,为探索大语言

weixin_36019375的博客 435

linux离线安装nginx

linux离线安装nginx

zhang_130914036的博客 9351

探讨C++列表在多线程环境下的性能表现与同步问题

例如,使用无锁链表(如boost::lockfree::list),它通过原子操作实现节点的插入和删除,减少了线程间的竞争,在高并发环境下能提供更好的性能表现。例如,将对std::list的操作分解为多个小操作,只在真正涉及共享数据修改的部分加锁,而其他不影响共享数据的操作可以在锁外执行,降低锁的竞争程度。3. 异步操作:将对std::list的一些耗时操作(如大规模数据的插入或删除)改为异步操作,通过消息队列等机制将操作请求发送到后台线程处理,避免主线程因等待操作完成而阻塞,提高整体的并发性能。

yzz19900508的博客 414

【Bug已解决】NCCL timeout for validation 解决方案

训练用多卡 DDP / FSDP 正常,但一到或者进程直接 hang 在 eval 的某个集合通信上。最迷惑的是:训练阶段(有集合通信)完全正常,偏偏 eval 阶段(看起来更轻量)超时。因为 eval 阶段某些 rank 没参与 collective,导致参与的那部分 rank 永远等不到同伴。

一键难忘的博客 143

C++多线程线程同步问题

一、进程线程概念 进程通常被定义为一个正在运行的程序的实例,是一个程序在其自身地址空间中的一次执行活动。 进程从来不执行任何东西,它是线程的容器。若要进程完成某项操作它必须拥有一个在它的环境中运行的线程,此线程负责包含执行包含在进程地址空间中的代码。 现存由线程的内核对象和线程栈两部分组成。操作系统用线程的内核对象来管理线程,内核对象也是系统用来存放线程统计信息的地方。线程栈用来维护程序在执行代码是所需要的所有函数参数和局部变量。 二、C++中线程创建函数 使用系统提供的API函数CreateT.

sinat_41928334的博客 1243

手把手教你完成YOLOv11分类识别界面搭建,使用Qt6设计YOLOv11分类识别系统,前台系统+后台管理系统开发实战,全网最详细教程

本项目结合YOLOv11分类识别算法和PySide6框架,开发了一套图形化分类识别系统。系统支持图片、视频和摄像头实时分类检测,并具备完善的用户管理功能,包括登录验证、个人信息修改等模块。最新版本新增了管理员后台管理系统,包含用户管理、权限控制等功能。系统采用MySQL数据库存储用户数据,界面设计采用QtDesigner完成,实现了高效的目标分类与友好的交互体验。

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 1054

基于STM32设计的物联网疫苗冷链物流监测系统

本设计基于物联网技术,开发了一套疫苗冷链物流环境监测系统。系统采用STM32F103C8T6作为主控芯片,集成SHT30温湿度传感器、震动传感器、GPS定位模块和4G通信模块,实现对运输环境的温度、湿度及震动状况的实时监测与控制。通过继电器驱动半导体制冷模块和加湿器,系统能够自动调节环境温湿度,保障疫苗运输的安全性。采集的环境数据通过MQTT协议上传至华为云物联网平台,配套开发的Android手机APP和Windows上位机软件基于Qt平台设计,支持远程实时查看环境数据和车辆定位,提升了疫苗冷链运输的智能化

866

C++多线程join同步问题

  其实就是想记录一下自己的想法,就是关于多个线程的执行顺序的思考。之前一直觉得std::thread::join会阻塞其他线程的运行,其实并不是这样子的。举个例子 std::vector<std::thread *>lt; for(int i = 35 ; i >20 ; i--) {   std::thread *t= new thread(show...

weixin_30599769的博客 1451

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

C++多线程中共享变量同步问题

多线程共享变量同步 1、互斥量 (1)std::mutex (2)std::recursive_mutex (3)std::timed_mutex 2、锁管理器 (1)std::lock_guardlk (2)std::unique_locklk (3)std::unique_lock第二个参数使用 3、条件变量 (1)std::condition_variable a>wait()函数 b>notify_one()函数 c>notify_all()函数 4、原子操作

hanxiaoyong_的博客 5222

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

c++ 多线程向同一个文本写入信息 解决同步与互斥问题

c++ 多线程向同一个文本写入信息 解决同步与互斥问题 作业:使用四个线程向一个文本内写入不同的内容,要求解决同步与互斥的问题。 目录 Windows多线程结构 Windows互斥锁解决同步问题 代码 Windows多线程结构: HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes,//SD:线程安全相关的属性,常置为NULL SIZE_T dwStackSize,//initialstacksize:新线程的初始化

TKXS 1851

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

多线程编程的基本概念,C++标准库中的多线程支持(std::thread,std::async),如何处理线程同步和并发问题。

多线程编程在现代计算机系统中非常重要,因为它能够使程序同时执行多个操作,提高计算效率。以下是多线程编程的基本概念及如何在C++标准库中使用和std::async进行多线程编程,同时处理线程同步和并发问题。

不会编程的码农研究僧 1692

c++ pipe 同步 互斥_哲学家就餐问题——深入了解多线程同步那些事

1971年,著名的计算机科学家艾兹格·迪科斯彻提出了一个同步问题,即假设有五台计算机同时去访问五份共享的内存数据,系统应该如何处理?后来为了方便表述和理解,演变成了计算机科学中大名鼎鼎的“哲学家就餐”问题,用来诠释系统死锁和资源耗尽的情况。多线程同步/互斥中常见的名词解释在具体介绍哲学家就餐问题前,我们需要明白一些名词的含义:多并发:系统在运行过程中遇到短时间内遇到大量操作请求的情况,例如对CPU...

weixin_29039773的博客 372

C++新特性28_线程同步问题的产生原因(高级语言转为低级语言执行,时间片交替运行多线程中代码,代码切换过程中出现的问题)

线程同步问题的产生原因(高级语言转为低级语言执行,时间片交替运行多线程中代码,代码切换过程中出现的问题)

分享学习成长历程,Winter is coming! 862
上一篇: 栈的弹出顺序是否正确
下一篇: 刷题1-多线程
Poo_Chai
博客等级 码龄9年 178粉丝 117原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Poo_Chai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值