第四章——读书笔记

这篇博客探讨了C++多线程系统编程的关键点,强调了线程安全的重要性,指出C++标准库中的大多数函数并非线程安全,并详细讨论了Linux上的线程标识问题。文章还提到了线程创建和销毁的准则,特别是`exit()`函数在多线程环境中的风险,以及如何善用`__thread`关键字。此外,还涉及了多线程与IO、RAII、`fork()`、`signal`在多线程环境下的行为和挑战。
摘要由CSDN通过智能技术生成

C++多线程系统编程精要

学习多线程编程面临的最大的思维方式的转变有两点

  • 当前线程可能随时会被切换出去,或者说被抢占了
  • 多线程程序中事件的发生顺序不再有全局统一的先后关系

当线程被切换回来继续执行下一条语句(指令)的时候,全局数据(包括当前进程在操作系统内核中的状态)可能已经被其他线程修改了。例如,在没有为指针p加锁的情况下,if(p && p->next)有可能导致段错误,因为逻辑与&&的前一个分支为true之后的一霎那,p可能被其他线程设置为NULL或者被释放,后一个分支就访问了非法地址。

在多核系统中,多个线程是并行执行的。在没有适当同步的情况下,多个CPU上运行的多个线程中的事件发生先后顺序是无法确定的。在引用适当同步后,事件之间才有了happens-before关系。

多线程程序的正确性不能依赖于任何一个线程的执行速度,不能通过原地等待来假定其他线程的事件已经发生,而必须通过适当的同步来让当前线程能看到其他线程的事件的结果。无论线程执行得快与慢,程序都应该能正常工作。

4.2 C/C++系统库的线程安全性

编写线程安全程序的一个难点在于线程安全是不可组合的,一个函数foo()调用了两个线程安全的函数,而这个foo()函数本身可能不是线程安全的。

可以遵循一个基本原则:凡是非共享的对象都是彼此独立的,如果一个对象从始至终只被一个线程用到,那么它就是安全的。另外一个事实标准是:共享的对象的read-only操作是安全的,前提是不能有并发的写操作。一旦有写操作,那么read-only操作必须加锁

根据对线程安全的定义,C++的标准库容器和std::string都不是线程安全的,只有std::allocator保证是线程安全的。

C++标准库中的绝大多数泛型算法是线程安全的,因为这些都是无状态纯函数。只要输入区间是线程安全的,那么泛型函数就是线程安全的。

C++的iostream不是线程安全的,因为流式输出

std::cout << "Now is" << time(NULL);

等价于两个函数调用

std::cout.operator<<("Now is ").operator<<(time(NULL));

4.3 Linux上的线程标识

POSIX threads库提供了pthread_self函数用于返回当前进程的标识符,其类型为pthread_tpthread_t不一定是一个数值类型(整数或指针),也有可能是一个结构体,因此Pthreads专门提供了pthread_equal函数用于对比两个线程标识符是否相等。

这样造成了一些问题

  • 无法打印输出pthread_t,因为不知道其确切类型。
  • 无法比较pthread_t的大小或计算其hash值。
  • 无法定义一个非法的pthread_t值,用来标识绝对不可能存在的线程id
  • pthread_t值只在进程内有意义,与操作系统的任务调度之间无法建立有效的关联。

另外,glibcPthreads实现实

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值