多线程的高并发总是个很tricky的事情. 为了避免操作系统的线程context switch成本, lock-free编程中用各种原子操作(CAS等和内存屏障). 极端的地方, 甚至CAS操作的成本都要考虑. 比如Java中的synchronized的偏向锁/轻量级锁优化就考虑减少CAS操作. 还有JUC包中的一些实现也是尽量减少CAS.
那么CAS大致上什么样的一个成本呢?
Performance-Critical的优化例子(1)
搬砖时, 很少碰到需要写发挥CPU极致性能的代码. 一般而言, 软件系统的性能瓶颈在上层的架构或算法,IO,内存带宽上. 对CPU优化的工作都一般都是编译器,虚拟机和底层各种runtime来处理.
当瓶颈在CPU上时, 比如特定领域的加密/压缩/视频图形解码等, 汇编优化很重要. 在大数据/云时代那些大规模部署的分布式程序能有个百分之几的优化省下不少的服务器, 一些关键的hotspot函数还是值得优化一下. 有时候得汇编加持, 追求极致性能.
汇编的一些奇技淫巧, 对日常搬砖没啥作用. 但因此而去了解一下CPU的front-end对我们用高级语言(C/C++/Java)搬高性能代码有些好处.
[Paxos]读The Part-Time Parliament笔记(一)
前两年看过Paxos协议, 网上各种通俗化解释, 更晕. 不如自己看论文. 自己没有实践中实现Paxos, 看chubby论文就知道坑非常多. 但理论上的理解,论文《The Part-Time Parliament》其实讲的很清晰.
这不是Paxos介绍讲解什么的, 只是读论文做的笔记, 把数学证明过程再证一次.
[并发系列-6] 从AQS到futex(四): Futex/Critical Section介绍
Futex(Fast Userspace muTexes),是Linux提供的最基础的并发原语, C runtime如glibc的mutex,join,condition variable,semphore都是基于futex实现.
[并发系列-5] 从AQS到futex(三): glibc(NPTL)的mutex/cond实现
上篇笔记大致看了Java同步互斥机制在JVM层的实现. HotSpot在Linux平台是用pthread实现. 这篇继续对glibc(NPTL)在Linux平台上如何实现mutex和condition做个笔记.
glibc的源码极其难读, 因为要处理平台区别,性能优化,特殊情况处理等等, 源码的可读性不在大神们的考虑之列. 这里不是逐行源码解读, 列出来的代码都不是glibc的原版代码, 改动和简化了方便理解.
- pthread_mutex_t和lock/unlock操作,
- low level lock的汇编实现, 最为tricky的地方
- pthread_cond_t和wait/signal.
[并发系列-4] 从AQS到futex(二): HotSpot的JavaThread和Parker
J.U.C.中AQS管理线程队列, LockSupport用来block/unblock线程. 通过HotSpot(Java 9)的源码来粗略的看看JVM这层的实现:
- HotSpot的Thread/JavaThread类的简介
- HotSpot的Parker的实现细节
[并发系列-3] 从AQS到futex(一): AQS和LockSupport
AQS(AbstractQueuedSynchronizer,同步器)是java.util.concurrenct包一个核心基础类, 来用构建锁或其他同步组件. 网上对这个的分析文章非常多,有源代码解读还有画出图示意线程队列的管理(链接). 也可以通过Doug Lea的AQS论文(中文版)看看AQS的设计思想.
从另外一个角度,纵向的深入一下:
- (JDK) J.U.C (AQS/LockSupport) =>
- (JVM) HotSpot (Thread/Parker) 线程和block/unblock实现 =>
- (C runtime) 到glibc中的pthread(NPTL)的实现 =>
- (Kernel) Linux内核的线程和futex的介绍
从AQS到HotSpot, 再到glibc, 最后到内核的futex. 纵向一条线深入下来, 粗略地了解下各个层次的实现, 做个笔记.
问: 整这个有用么?
答: 可能没啥具体作用. 还是类似孔乙己写回字.
Markus K在塞维利亚街头的布鲁斯表演
再听Markus K的布鲁斯, 还是很好听.
去年去塞维利亚参加ApacheCon, 最后一天的下午阳光很好,上街瞎逛. 碰到了Markus K的街头表演. 这是我近年来听到最好听的音乐(之一), 很喜欢这种风格的布鲁斯.
Markus K is busking on the street in Seville(手机录的,效果很差):
[并发系列-2] 为什么要有Condition Variable?
儿子最近不在家, 我开机时也没人过来胡乱锤打我的键盘了. 有空来写篇技术文章, 不是宏大的分布式大数据深度学习啥, 深入扣个细节, 就像孔乙己写”回”字, 回囘囬廻…
Condition Variable是个同步原语(synchronization primitives), 用来协调不同线程的逻辑顺序. 和实习生同事小T讨论时, 谈到了两个问题:
- 有了mutex, 为啥还要整个Condition variable的概念出来?
- Condition为什么要跟一个锁(mutex)一起用? 比如, pthread_cond_wait(cond, mutex), 再比如Java里的condition是由锁newCondion()生成.
我觉得这两问题很有深度, 小结一下我个人的理解.
[并发系列-1] 由wait/sleep例子开始
0. 引子
实习生同事小T和我讨论, Java里的wait和sleep区别, 他网上一查, 答案大概都是:
- sleep 不会释放锁; 而wait 会释放锁
- wait要先synchronized
|
|
打破砂锅问到底的小T不满意答案,
- 啥叫释放锁持有锁? 啥叫阻塞队列
- 线程怎么放弃或拿到CPU的时间切片