第4章 C++多线程系统编程精要

  • Pthreads只保证统一进程之内,同一时刻的各个线程的id不同,不能保证同一进程先后多个进程具有不同的id,更不要说一台机器上多个进程之间的id唯一性,pthread_t不适合用做程序对线程的标识符。

  • 推荐使用**gettid()**的返回值作为线程id

    • 返回值类型pid_t,通常是小整数,便于在日志输出
    • 可以在/proc文件系统中找到对应项,/proc/tid,/proc/pid/task/tid
    • 任何时候全局唯一
    • top判断CPU占有最高的线程id
    • pid = 0非法,系统的第一个进程init的pid = 1

4.1 线程的创建和销毁应该遵循的原则

  • 程序库不应该在未提前告知的情况下创建自己的“背景线程”
  • 尽量用相同的方式创建线程
  • 在进入main()函数之前不应该启动线程
  • 程序中线程的创建最好能在初始化阶段全部完成

4.2 线程的销毁方式

  • 自然死亡,从线程主函数返回,线程正常退出
  • 非正常死亡,从县城主函数抛出异常或线程触发segfault信号等非法操作
  • 自杀,在线程中调用pthread_exit()来立刻退出线程
  • 他杀,其他线程调用pthread_cancel()来强制终止某个线程

线程正常退出的方式只有一种,自然死亡。强制终止线程的话,没有机会清除所有的资源,也没有机会释放已经持有的锁,其他线程如果对同一个mutex加锁,那么他就会立刻死锁。

如果程序中线程的创建能在初始化阶段全部完成,线程是不必销毁的,伴随程序的一直运行,彻底避开了线程安全退出可能面临的各种困难

4.3 exit在C++中不是线程安全的

exit()函数在C++中的作用除了终止进程,还会析构全局对象和已经构造完的函数静态对象。这回潜在的死锁可能

void someFunctionMayCallExit() {exit(1);
}
class GlobalObject {public:void doit() {MutexLockGuard lock(mutex_);someFunctionMayCallExit();}~GlobalObject() {printf("GlobalObject: ~GlobalObject\n");MutexLockGuard lock(mutex_); // 死锁//clean upprintf("GlobalObject:~GlobalObject cleanning\n");}
private:MutexLock mutex_;
};GlobalObject g_obj;
int main() {g_obj.doit();
}

4.4 多线程与IO

  • 多线程与IO可能存在的问题:

    • 线程正在阻塞read()某个socket,另一个线程close()这个socket

    • 线程正在阻塞的accept()某个listening socket,另一个线程close()这个socket

    • 线程准备read()某个socket,另一个线程close()socket,第三个线程又open()了相同的fd的socket。POSIX标准要求每次新打开的文件使用当前最小的可用的文件描述符

  • 为什么服务端程序不应该关闭标准输出和标准出错?

    有些第三方库会向stdout和stderr打印出错信息,如果程序关闭了标准输入和标准出错,可能被网络连接占用,造成对方收到莫名其妙的数据。正确的做法是把stdout和stderr重定向到磁盘文件

4.5 多线程与fork

fork()之后,子进程继承了父进程的几乎全部状态,有些少数例外。子进程会继承地址空间和文件描述符。

子进程不会继承的有:

  • 父进程的内存锁,mlock,mlockall
  • 父进程的文件锁,fcntl
  • 父进程的某些定时器,setitimer,alarm,timer_create
  • 其他

fork()之后子进程只有一个线程,其他线程都消失了。这可能存在隐患:一些线程持有锁处于临界区,而子线程试图对同一个mutex加锁,这会造成死锁。

fork()之后,子进程不能调用:

  • malloc,malloc在访问全局状态时,几乎肯定会加锁
  • 任何可能分配或释放内存的函数,new,map::insert(),snprintf
  • 任何pthread函数
  • printf函数,其他线程可能恰好持有stdout/stderr锁
  • 除了signal安全函数之外的任何函数

唯一安全的做法是在fork()之后立即调用exec()执行另一个程序,彻底隔断子进程与父进程的联系

muduo学习笔记 - 第4章 C++多线程系统编程精要相关推荐

  1. muduo学习笔记 - 第1章 C++多线程系统编程

    第1章 C++多线程系统编程 1.1 智能指针 C++中动态内存管理是用new和delete完成. 动态内存管理经常出现两种问题: 忘记释放内存造成内存泄露 还有指针引用的内存的情况下释放内存,造成引 ...

  2. muduo学习笔记 - 第五章 高效的多线程日志

    第五章 高效的多线程日志 日志有两种意思: 诊断日志 交易日志 本章讲的是前一种日志,文本的供人阅读的日志,通常用于故障诊断和追踪,也可用于性能分析. 日志通常要记录: 收到的每条消息的id(关键字段 ...

  3. muduo学习笔记 - 第3章 多线程服务器的适合场合与常用编程模型

    第3章 多线程服务器的适合场合与常用编程模型 3.1 基本概念 同步和异步 针对程序和内核的交互 同步:用户进程触发IO操作,等待或轮询的查看IO是否就绪 异步:用户进程触发IO操作,继续做自己的事情 ...

  4. muduo学习笔记 - 第2章 线程同步精要

    第2章 线程同步精要 2.1 互斥器 (mutex) 互斥器保护了临界区,任何时刻最多只能有一个线程在mutex划出的临界区内活动 推荐使用原则: 用RAII手法封装mutex的创建.销毁.加锁.解锁 ...

  5. 计算机组成原理学习笔记第8章I/O系统 8.2 输入/输出方式

    名人说:非学无以广才,非志无以成学.--诸葛亮 本篇笔记整理:Code_流苏(CSDN) Last(在此处点击使用,直达文末) First (在文末点击使用,返回文章首部) 目录 1.输入/输出方式 ...

  6. UNP学习笔记-第三章套接字编程

    套接字地址结构 地址转换函数 地址转换函数在地址的文本表达和存放在套接字地址结构中的二进制值之间进行转换. 例如IPv4中inet_addr, inet_ntoa .新函数:inet_pton,ine ...

  7. Java 学习笔记:第一章 Java入门

    Java 学习笔记:第一章 Java入门 1.1 计算机语言发展史以及未来方向 1.2 常见编程语言介绍 C语言 C++ 语言 Java语言 PHP 语言 Object-C和Swift 语言 Java ...

  8. CCSP-防火墙学习笔记第6章

    CCSP-防火墙学习笔记第6章-Netemu首发 第6章刚刚完成,排版上更具层次化,等第7章完结后,将会重新把1-7章的内容编好目录.作为Cisco防火墙学习笔记的初级篇发布 高级特性将会在第8章讨论 ...

  9. Programming Entity Framework-dbContext 学习笔记第五章

    ### Programming Entity Framework-dbContext 学习笔记 第五章 将图表添加到Context中的方式及容易出现的错误 方法 结果 警告 Add Root 图标中的 ...

最新文章

  1. BSP(BUSINESS SERVER PAGES)完整主机名设置及实现
  2. 织梦dedecms实现按照字母搜索的实现方法
  3. Android 通过代码改变控件的布局方式
  4. Less taolu
  5. windows python安装_window 安装 python
  6. 项目管理十大知识领域,为何不含
  7. 六大举措深耕光通信市场
  8. 抖音联合巨量引擎、飞书推出五项举措 助中小企业共度疫情难关
  9. 95-190-452-源码-window-Trigger-ContinuousEventTimeTrigger
  10. [转] Float或Double浮点型计算精度问题的解决方法
  11. 单目标跟踪paper小综述
  12. 三人表决器实验报告总结_三人表决器实验报告.doc
  13. kettle 使用教程(入门)
  14. halcon 1维测量
  15. STM32CUDE-STM32F407学习笔记1-点亮LED
  16. Python爬虫 刷博客访问量
  17. 一个三流学校程序员的奋斗!(转)
  18. 压力位和支撑位的理解。
  19. LCD1602液晶显示屏用51单片机怎么驱动?(详细笔记附设计源码)
  20. 《2019全球货运代理TOP25、全球第三方物流Top50排行榜》

热门文章

  1. 从 0 到 1 实现 React 系列 —— 2.组件和 state|props
  2. 关于Python Profilers性能分析器
  3. 复杂链表的复制(递归的两种实现方式)
  4. 用CURD来拯救前端的一切的一切
  5. C#中要使一个类支持FOREACH遍历,实现过程怎样? [转]
  6. 命令获取计算机信息,教你怎么在windows上用命令查看系统信息
  7. HarmonyOS之深入解析蓝牙Bluetooth的功能和使用
  8. Algorithm Master Road:算法的时间/空间复杂度
  9. 2019年第十届蓝桥杯 - 省赛 - C/C++大学B组 - H. 等差数列
  10. DRF的序列化——Serializers 序列化组件