《Linux多线程服务端编程》笔记——线程同步精要
来源:互联网 发布:java jar 日志输出 编辑:程序博客网 时间:2024/05/17 05:59
并发编程基本模型
message passing和shared memory。
线程同步的四项原则
- 尽量最低限度地共享对象,减少需要同步的场合。如果确实需要,优先考虑共享 immutable 对象。
- 使用高级的并发编程构件,如TaskQueue、Producer-Consumer Queue、CountDownLatch等等。
- 不得已必须使用底层同步原语(primitives)时,只用非递归的互斥器和条件变量,慎用读写锁,不要用信号量。
- 除了使用 atomic 整数之外,不自己编写 lock-free 代码,也不要用“内核级”同步原语。不凭空猜测“哪种做法性能会更好”,比如 spin lock vs. mutex。
互斥器的使用
- 用 RAII 手法封装 mutex 的创建、销毁、加锁、解锁这四个操作。保证锁的生效期间等于一个作用域(scope)。
- 只用非递归的 mutex(即不可重入的 mutex)。
- 不手工调用 lock() 和 unlock() 函数,一切交给栈上的 Guard 对象的构造和析构函数负责(Scoped Locking)。
- 在每次构造 Guard 对象的时候,思考一路上(调用栈上)已经持有的锁,防止因加锁顺序不同而导致死锁。
条件变量的使用
对于 wait() 端:
必须与 mutex 一起使用,该布尔表达式的读写需受此 mutex 的保护。
在 mutex 已上锁的情况下才能调用 wait()。
把判断布尔表达式和 wait() 放在 while 循环中。对于 signal/broadcast 端:
不一定要在 mutex 已上锁的情况下调用 signal(理论上)。
在 signal 之前一般要修改布尔表达式。
修改布尔表达式通常需要用 mutex 保护(至少用作 full memory barrier)。
broadcast 通常用于表明状态变化,signal 通常用于表示资源可用。虚假唤醒(spurious wakeup),Linux 中 futex 慢速系统调用被信号打断返回 -1,wait 返回了。
读写锁与信号量的使用
- 从正确性方面来说,一种典型的易犯的错误是在持有 reader lock 的时候修改了共享数据。
- 从性能方面来说,读写锁不见得比普通 mutex 更高效。
- reader lock 可能允许提升为 writer lock,也可能不允许提升。
- 通常 reader lock 是可重入的,writer lock 是不可重入的。
- 信号量不是必备的同步原语,因为条件变量配合互斥器可以完全替代其功能,而且更不易用错。
参考:《Linux多线程服务端编程》。
0 0
- 《Linux多线程服务端编程》笔记——线程同步精要
- 《Linux多线程服务端编程》—线程同步精要
- linux多线程编程精要
- 多线程编程学习笔记——线程同步(三)
- 多线程编程——线程同步方法
- 多线程编程2——线程同步
- Java多线程编程— 线程同步问题
- 《Linux多线程服务端编程》读书笔记——第一章_线程安全的对象生命期管理
- 《Linux多线程服务端编程》—线程安全的对象生命期管理
- Linux多线程服务端编程(笔记1)
- Linux多线程服务端编程(笔记2)
- 《Linux多线程服务端编程》学习笔记---第一章
- linux多线程编程---线程同步之互斥锁
- Linux 多线程编程----线程见同步问题
- Linux多线程编程之线程同步操作
- Java6学习笔记59——多线程编程——线程的同步(version 0.2)
- Java多线程编程总结笔记——六线程的同步与锁
- 多线程编程:线程同步
- [数据挖掘]
- Android UI 开发入门—线性布局练习
- 2种方法解决mysql主从不同步
- [转]关于软件测试的几个经典问题(2)
- java创建二叉树及遍历
- 《Linux多线程服务端编程》笔记——线程同步精要
- 字符char 输入输出流 和 NIO
- Mysql 优化之 Explain 执行计划
- Java学习-装箱和拆箱
- leetCode:493. Reverse Pairs
- iMX283 学习笔记----1. GPIO2_4(P2.4) 操作
- 设计模式C++实现(1)——工厂模式
- 各种算法的优缺点
- 华师大 OJ 3036