C++ 菜鸟之路 (四) boost::thread 多线程全解析

2023-05-16

  • boost::thread 的一般用法
    • boost::thread的几个函数
  • 锁 - lock ( ) 函数
  • 多线程函数的限制

官方解释: http://www.cplusplus.com/reference/thread/thread/joinable/

boost::thread 的一般用法

/*
thread.cpp
*/
#include <boost/thread/thread.hpp> 
#include <iostream> 

#include <unistd.h>

/* 
 * g++ thread.cpp -lboost_system -lboost_thread
*/

void helloA() 
{ 
        std::cout << "I'm thread A !  --- Start " << std::endl; 

        sleep(10);

        std::cout << "I'm thread A !  --- OVER " << std::endl; 

} 


  void helloB() 
{ 
        std::cout << "I'm thread B !  --- Start " << std::endl; 

        sleep(10);

        std::cout << "I'm thread B !  --- OVER " << std::endl; 

} 

int main(int argc, char* argv[]) 
{ 
        boost::thread thrdA(&helloA);
        boost::thread thrdB(&helloB);  
        thrdA.join();
        thrdB.join(); 
        // join() 的作用是让主进程等待子线程执行完毕后再继续执行。
        // 否则会不检查子线程执行状况,直接退出了。
        return 0; 
} 


/*结果
I'm thread A !  --- Start 
I'm thread B !  --- Start 
I'm thread A !  --- OVER 
I'm thread B !  --- OVER 
*/

编译方式:

g++ thread.cpp -lboost_system -lboost_thread

如果直接采用 g++ thread.cpp 会出现如下的错误,

/tmp/ccoutPZ3.o: In function `__static_initialization_and_destruction_0(int, int)':
thread.cpp:(.text+0xce): undefined reference to `boost::system::generic_category()'
thread.cpp:(.text+0xda): undefined reference to `boost::system::generic_category()'
thread.cpp:(.text+0xe6): undefined reference to `boost::system::system_category()'

参考这个回答:
https://stackoverflow.com/questions/13467072/c-boost-undefined-reference-to-boostsystemgeneric-category 是因为这里找不到链接库, 所以需要 -lboost_system 和 -lboost_thread

boost::thread的几个函数

函数功能
join()让主进程等待子线程执行完毕后再继续执行
get_id()获得线程的 id 号
detach()标线程就成为了守护线程,驻留后台运行
bool joinable()是否为 join()

thread::join()是个简单暴力的方法,主线程等待子进程期间什么都不能做,一般情形是主线程创建thread object后做自己的工作而不是简单停留在join上。
thread::join()还会清理子线程相关的内存空间,此后thread object将不再和这个子线程相关了,即thread object不再joinable了,所以join对于一个子线程来说只可以被调用一次,为了实现更精细的线程等待机制,可以使用条件变量等机制。

1、可会合(joinable):这种关系下,主线程需要明确执行等待操作,在子线程结束后,主线程的等待操作执行完毕,子线程和主线程会合,这时主线程继续执行等待操作之后的下一步操作。主线程必须会合可会合的子线程。在主线程的线程函数内部调用子线程对象的wait函数实现,即使子线程能够在主线程之前执行完毕,进入终止态,也必须执行会合操作,否则,系统永远不会主动销毁线程,分配给该线程的系统资源也永远不会释放。

2、相分离(detached):表示子线程无需和主线程会合,也就是相分离的,这种情况下,子线程一旦进入终止状态,这种方式常用在线程数较多的情况下,有时让主线程逐个等待子线程结束,或者让主线程安排每个子线程结束的等待顺序,是很困难或不可能的,所以在并发子线程较多的情况下,这种方式也会经常使用。

锁 - lock ( ) 函数

#include <boost/thread/thread.hpp> 
#include <boost/thread/mutex.hpp> //定义锁
#include <iostream> 

#include <unistd.h>

/* 
 * g++ thread.cpp -lboost_system -lboost_thread
*/

//boost::shared_mutex  read_write_mutex;
boost::mutex lock; //使用的锁

using namespace std;
int num = 100;
void helloA() 
{ 
        std::cout << "I'm thread A ! " << boost::this_thread::get_id()  << " --- Start " << std::endl; 

        lock.lock(); // 锁住变量 num, 另一处调用将在此处运行完后再继续运行

        num++;

        std::cout << num <<std::endl;

        sleep(3);

        lock.unlock();

        std::cout << "I'm thread A !  --- OVER " << std::endl; 

} 


  void helloB() 
{ 
        std::cout << "I'm thread B ! " << boost::this_thread::get_id()  << " --- Start " << std::endl; 

        lock.lock(); 

        num++;

        std::cout << num <<std::endl;

        sleep(3);

        lock.unlock();

        std::cout << "I'm thread B !  --- OVER " << std::endl; 

} 

int main(int argc, char* argv[]) 
{ 
        // 建立并执行两个线程

        boost::thread thrdA(&helloA);


        boost::thread thrdB(&helloB);  


        thrdA.join(); // 等待子线程完成后再继续执行主进程;


        thrdB.join();


        // 等待两个 join 后才会继续执行
        cout<< " ==== over ==== "<<endl;

        return 0; 
} 

/*结果
I'm thread A ! 7f5792ddc700 --- Start 
101 
I'm thread B ! 7f57925db700 --- Start 
I'm thread A !  --- OVER 
102
I'm thread B !  --- OVER 
 ==== over ====

数据 num 被锁住, 线程B中的 num 将不能修该。 所以线程A 执行完才能修改 num 的值, 才能执行线程B。
*/

多线程函数的限制

工作的时候, 想让发布地图单独占用一个线程, 但是发现一些问题。

    boost::thread thrdA(&updateMap)
    thrdA.join();
    /*
    if(updateMap())
    {
        ROS_DEBUG("Updated the map");
        }
    */
    return;

编译的时候出现如下的错误

error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function.  Say ‘&SlamKarto::updateMap’ [-fpermissive]
  boost::thread thrdA(&updateMap);
                       ^
In file included from /usr/include/boost/thread/thread_only.hpp:22:0,
                 from /usr/include/boost/thread/thread.hpp:12,
                 from /usr/include/boost/thread.hpp:13,
                 from /opt/ros/indigo/include/tf/transform_listener.h:43,
                 from /home/moi/SLAM_Gmapping/src/slam_karto/src/slam_karto.cpp:31:
/usr/include/boost/thread/detail/thread.hpp: In instantiation of ‘void boost::detail::thread_data<F>::run() [with F = bool (SlamKarto::*)()]’:

大意错误就是, 多线程函数不能是非静态成员函数, 于是我再各个函数上加了 static bool SlamKarto::updateMap( ) 但是编译再次出错, 还是很傻的错误。

error: invalid use of member ‘SlamKarto::map_mutex_’ in static member function
   boost::mutex map_mutex_;
// 原函数包含太多的非静态成员
(1)普通数据成员属于类的一个具体的对象,只有对象被创建了,普通数据成员才会被分配内存。而静态数据成员属于整个类,即使没有任何对象创建,类的静态数据成员变量也存在。
(2)因为类的静态数据成员的存在不依赖与于任何类对象的存在,类的静态数据成员应该在代码中被显式地初始化,一般要在类外进行,例如上例。在C++11标准中,我们可以为静态成员提供const整数类型的类内初始值,不过要求静态成员必须是字面值常量类型的constexpr(源自C++Primer中文版270页)。
(3)外部访问类的静态成员能直接通过类名来访问,例如:test::getCount()。虽然静态成员不属于类的某个对象,但是我们仍然可以使用类的对象、引用或指针来访问静态成员(源自C++Primer中文版269页),例如:
test ac1,*ac2;
int r;
r=ac1.getCount();// 或者 r=ac2->getCount();
(4)类的静态成员函数无法直接访问普通数据成员(可以通过对象名间接的访问),而类的任何成员函数都可以访问类的静态数据成员。
(5)静态成员和类的普通成员一样,也具有public、protected、private3种访问级别,也可以具有返回值、const修饰符等参数。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 菜鸟之路 (四) boost::thread 多线程全解析 的相关文章

  • C语言中关于int、long int、long long 的区别

    1 关于int 和 long int xff08 1 xff09 在VC下没有区别 两种类型均用4个字节存放数据 xff08 2 xff09 VC是后出的编译器 xff0c 之前有很多早期的C编译器 xff0c 在早期编译器下long in
  • arp a命令的通俗解释

    ARP A 查询系统中缓存的ARP表 ARP表用来维护IP地址与MAC地址的一一对应 比方说 xff0c 某推拿室总有30名服务员 xff0c 为了方便管理 xff0c 服务员都编了号 xff0c 由01编到30 客人们都只记得服务员的编号
  • sqlite模糊查询与分页

    sqlite模糊查询与分页 64 param queryWords 要查询的关键词 xff08 中英文都可以 xff09 64 param curItem 当前查询到的item 所在位置 64 param sizeRequest 每次请求查
  • 设计模式-回调函数和观察者模式

    Android的框架中有非常多的地方使用了回调的模式 xff0c 例如Activity的生命周期 xff0c 按钮的点击事件等 下面是回调的基本模型 xff1a java view plain copy public class A pri
  • QT之表格控件

    目录 一 xff1a 表格控件 1 QTableWidget表格的创建 1 QTableWidgetItem单元格 2 表格的信号和槽 3 代码引例 1 在 h文件中定义 2 在main文件中创建并实现 4 结果演示 GIF 一 xff1a
  • sequlize统一格式化时间

    数据查出来的数据格式 xff0c 如图 xff1a 自动格式化时间 xff0c 需要在数据库配置上加上 dateStrings true
  • Node 微信支付 “由于商家传入的H5交易参数有误 该笔交易暂时无法完成 请联系商家解决”

    之前稳定运行一段时间的微信H5支付 xff0c 突然报错 xff1a 由于商家传入的H5交易参数有误 该笔交易暂时无法完成 请联系商家解决 经过多方排查 xff0c 最终确定是微信下单的ip传递有误 上传的ip为 127 0 0 1 xff
  • css data:image/svg+xml 不显示

    原因 xff1a 新版chrome不支持 需要改成 23 如 xff1a test span class token punctuation span content url span class token punctuation spa
  • border-image属性分析

    border image是CSS3的一个属性 xff0c 由于比较复杂 xff0c 总是处于一知半解的状态 xff0c 今天下定决心 xff0c 花时间整理了一下 xff0c 供大家共勉和学习 border image的用处 没用borde
  • 纯CSS绘制箭头

    这几天研究别人的网站 xff0c 发现别人的箭头居然是用纯CSS写的 瞬间觉得高大上 细细研究其中的原理 xff0c 发现其实也很简单 CSS绘制三角形 绘制箭头 xff0c 首先应该懂得如何用纯CSS绘制三角形 我们先做一个宽高为0 xf
  • 如何更新npm至最新版本

    去年曾遇到过执行npm某项命令时提示要求更高版本的npm xff0c 当时百度解决了 xff0c 今天又再次遇到该问题 现记下来 xff0c 以供以后参考 命令行运行 xff1a span class hljs built in npm s
  • .*? 和 .*的区别

    在看js代码的时候 xff0c 有时候会遇到 这样的写法 xff0c 那么连续两个限制符是什么意思呢 xff1f 我们先来回顾一下正则表达式的基本知识 基本语法 符号用法 匹配除 r n 之外的任何单个字符 要匹配包括 r n 在内的任何字
  • 微信清除缓存的两种方法

    网址清除 微信浏览器打开网址 http debugx5 qq com xff0c 勾选如下设置 xff1a 点击 清除 按钮即可 代码清除 如果是自己写的网页 xff0c 在调试阶段希望不要缓存 xff0c 可以在html页面的head中加
  • PHP时间戳和日期转换

    时间戳转日期 date date format timestamp format 必需 规定时间戳的格式 timestamp 可选 规定时间戳 默认是当前时间和日期 例如 xff1a date Y m d H i s 具体时间戳 Y xff
  • 微信H5支付:网络环境未能通过安全验证,请稍后再试

    最近在开发微信H5支付 xff0c 并且已应用到某个网站进行支付 但奇怪的是 xff0c 一模一样的支付代码 xff0c 换了一个网站 xff0c 竟不能支付了 出现如图错误提示 xff1a 百度一圈 xff0c 均是说IP传得不对 微信s
  • 如何比较字符串大小

    今天我分享的是如何比较字符串的大小 xff0c 希望大家看完能有深刻的理解 字符比较 xff08 character comparison xff09 是指按照字典次序对单个字符或字符串进行比较大小的操作 xff0c 一般都是以ASCII码
  • node异步用await和不用await的区别

    最近在用node写项目 新版node异步用的是async await这两个关键字 我们都知道 xff0c 一般这两个关键字要成对出现 但是 xff0c 笔者发现 xff0c 如果不需要等待返回值的话 xff0c await可以不加 那么aw
  • NtripShare Cloud差分数据共享云平台

    RTK差分数据共享猫已更新至1 6 2版本 xff0c APP运行十分稳定 高级版本服务器已升级至华为云 xff0c 独享10M带宽 xff0c 进一步降低数据延迟 近期准备升级普通版服务器 xff0c 升级后将停止对1 6 0版本之前的不
  • RTK差分共享猫APP后台系统已开源

    RTK差分共享猫APP后台系统开源 xff0c 开源地址https gitee com forgy NtripShareCatServer 后台系统基于GUNS 6 0 xff08 https gitee com stylefeng gun
  • RTK差分数据网络播发软件

    解决短基线范围内多台设备同时作业 xff0c CORS差分账号资源不足的问题 基于串口或模拟网络RTK请求 xff0c 将实时差分数据进行转发 xff0c 支持Ntrip协议 xff0c 支持市面所有网络RTK系统 个人作品 xff0c 不

随机推荐

  • STM32使用cubemx的uart空闲中断接收不定长度数据

    void USART3 IRQHandler void USER CODE BEGIN USART3 IRQn 0 USER CODE END USART3 IRQn 0 HAL UART IRQHandler amp huart3 USE
  • 基于ROS平台的移动机器人-8-使用Kinect2导航

    基于ROS平台的移动机器人 8 使用Kinect2导航 ready 终于到写最后一篇了 不是经常写博文的老司机果然伤不起 xff01 在这一篇教程就是利用KinectV2来导航啦 go 1 安装一下所需的包 xff08 1 xff09 cd
  • kali linux学习——安装WingIDE(libqt4-webkit软件依靠问题)

    kali linux 中安装wingide xff08 libqt4 webkit软件依靠问题 xff09 走过的坑缺失的libqt4 webkit成功安装WingIDE 走过的坑 在kali linux上利用命令 dpkg i wingi
  • 华为的OD,值得去吗?

    最近有不少小伙伴接到了华为OD的面试邀约 xff0c 但搞不清楚OD到底怎么回事儿 xff0c 要不要去 所以今天来说说华为的OD到底是怎么回事儿 xff0c 怎么判断是否值得去 1 华为的OD是怎么回事儿 OD xff0c 是Outsou
  • 第01课:技术成长的三阶段模型

    引言 作为整个系统课程的第一部分 xff0c 我想先跟大家分享的是如何选择技术方向 xff0c 我将结合技术成长的三阶段模型 xff0c 讨论在入行 构建技能树 技术转型 团队技术方案选型等常见场景中如何选择适合自己的技术 努力只有在方向正
  • 开篇词 | 程序员的成长课

    大家好 xff0c 我是安晓辉 xff0c 做过开发工程师 研发经理 技术总监等岗位 xff0c 现在自由职业 xff0c 专注写作和开发者生涯咨询 出版过 程序员的成长课 Qt Quick 核心编程 你好哇 xff0c 程序员 解忧程序员
  • const与define的区别

    1 define是预编译指令 xff0c const是普通变量的定义 xff0c define定义的宏是在预处理阶段展开的 xff0c 而const定义的只读变量是在编译运行阶段使用的 2 const定义的是变量 xff0c 而define
  • 如何摆脱CRUD等打杂状态,从事更高价值工作

    每个月都会有十来个来询者向我抱怨工作低端 xff0c 程序员说自己每天CRUD xff0c 重复 枯燥 没技术含量 xff0c 销售助理说自己天天搜集客户信息 打印资料 帮老大带饭 xff0c 繁琐 无聊 不重要 xff0c 他们都说自己整
  • Windows下Qt 5.2 for Android开发入门

    Qt 5 2 发布了 xff0c 支持 Android 平台 xff0c 太好了 之前公司项目 xff0c 为了移植一个依赖 Qt 的程序到安卓平台上 xff0c 我自己交叉编译了 Qt Embedded 4 5 2 xff0c 费了老大劲
  • Qt Quick 之 QML 与 C++ 混合编程详解

    Qt Quick 技术的引入 xff0c 使得你能够快速构建 UI xff0c 具有动画 各种绚丽效果的 UI 都不在话下 但它不是万能的 xff0c 也有很多局限性 xff0c 原来 Qt 的一些技术 xff0c 比如低阶的网络编程如 Q
  • 漫谈程序员系列:一张图道尽程序员的出路

    推背图 相传由唐太宗时期的司天监李淳风和袁天罡合著 xff08 此两人其实是超级武学高手 xff0c 参见小椴的 开唐 xff09 xff0c 推算大唐以后中国两千多年的国运盛衰 xff0c 在中国七大预言书中居首 xff0c 是当之无愧的
  • 漫谈程序员系列:咦,你也在混日子啊

    戳你一下 xff0c 疼吗 xff1f 混日子的定义 来自百度百科的定义 xff1a 生活等方面过得不怎么好 xff0c 无目标 xff0c 混混沌沌 混日子 xff1a 即没有理想 xff0c 没有抱负 xff0c 糊里糊涂地生活 也指工
  • QtAndroid详解(1):QAndroidJniObject

    Qt 5 3之后 xff0c 新增了 QtAndroid 名字空间 xff0c 内有下列四个方法 xff1a QAndroidJniObject AndroidActivity int androidSdkVersion void star
  • freeSWITCH安装、配置与局域网测试

    这次来说说 freeSWITCH 的安装和配置 1 安装 freeSWITCH 下载页面 xff1a https freeswitch org confluence display FREESWITCH Installation 我们 Wi
  • 就 3 点,提升工作效率

    要想提高工作效率 xff0c 不论你看什么书 xff0c 看什么文章 xff0c 用什么工具 xff0c 只有下面这三点最重要 xff1a 动力剖析自己 xff0c 找到改善的切入点付诸行动并且坚持 目标驱动 有目标才能高效 我们爬山 xf
  • Python3 下 ROS 的使用 cv_bridge

    Python 3 下 ROSmsg 转 cv2 项目中用到的 Tensorflow2 4 的环境 xff0c 该环境只支持python3 版本 xff0c 项目中遇到不少需要和 ROS 交互的地方 xff0c 所以不断探索 python3
  • 深度图和RGB图对齐

    深度图 canny RGB canny Alignment xff1a code span class token function import span cv2 span class token function import span
  • 认识romfs文件系统

    1 1 什么是romfs romfs 是一个只读文件系统 xff0c 主要用在 mainly for initial RAM disks of installation disks 使用romfs 文件系统可以构造出一个最小的内核 xff0
  • Livox Lidar 特征提取方式总结

    传统的 旋转式雷达 xff0c 激光固定在雷达的旋转部件上 xff0c 依靠转子的转动而获得360的旋转视野 xff0c 由于旋转部件的存在 xff0c 为了获得更加精准的数据 xff0c 需要跟多的人工校准和更复杂的设计 xff0c 也因
  • C++ 菜鸟之路 (四) boost::thread 多线程全解析

    boost thread 的一般用法 boost thread的几个函数 锁 lock 函数多线程函数的限制 官方解释 xff1a http www cplusplus com reference thread thread joinabl