知识卡片
并发三难题
内容
并发正确性通常绕不开三件事:原子性保证操作不被打断(sum++ 反汇编后是4条独立字节码指令,中间可被切走);可见性保证一个线程的写入能被别的线程看到(JMM 规定线程先把主存变量复制到私有工作内存操作,回刷时机不固定,另一线程可能读到旧值);有序性保证执行顺序不被错误推断(重排序只保证单线程结果不变,多线程共享可变数据时可能出错)。锁、volatile、CAS、HB 都是在组合解决这三件事。
参考来源
- 位置:《Java高并发核心编程.卷2,多线程、锁、JMM、JUC、高并发设计模式》第4章《可见性与有序性的原理》4.2.1节《原子性问题》、4.2.2节《可见性问题》、4.2.3节《有序性问题》(源文件:_epub-src/OEBPS/Text/chapter124.xhtml、chapter125.xhtml、chapter126.xhtml)
- 结论依据:原文用 javap 反汇编 `sum++` 证明它是4条独立指令、可被线程切换打断(原子性问题);用线程A/B并发读写主存变量sum说明工作内存与主存不同步导致的丢失更新(可见性问题);用InstructionReorder示例展示重排序导致(0,0)的异常结果(有序性问题);并在结尾总结“要想并发程序正确地执行,必须要保证原子性、可见性以及有序性”,因此推出本卡结论。
- 原始内容:通过以上4个关键性的汇编指令可以看出,在汇编代码的层面,++操作实质上是4个操作……所有线程都必须将共享变量刷新到主存……要想并发程序正确地执行,必须要保证原子性、可见性以及有序性。只要有一个没有得到保证,就有可能会导致程序运行不正确。