12.2 理解JMM
JMM视图提供诸如一下问题的答案:
- 当两个处理器核心访问相同的数据时会发生什么?
- 什么时候能够保证它们看到的值是相同的?
- 内存缓存对这些答案有什么影响?
在现代的Java并发到来之前,使用Java的synchronized关键字是保证数据跨多个线程的排序和可见性的唯一机制。
JMM会强制实施这种行为,并为Java和内存安全的假设提供各种保证。然而,传统的Java的synchronized锁有以下几个局限性
- 同等对待已锁定对象上的所有synchronized操作。
- 锁的获取和释放必须在一个方法的级别或一个方法内的synchronized块内完成
- 要么获取锁,要么线程被阻塞;如果无法获取锁,则无法尝试获取锁并继续执行处理。
比如,读操作似乎不需要锁,但它必须使用synchronized来保证来自其他线程的更新的可见性。
12.3 构建并发库
java.util.concurrent中设计的库使得编写多线程更容易。开发者可以选择最适合自己需求的抽象层次,从java.util.concurrent选择抽象恰当的库还能带来更好的“多线程”性能。
Java提供的核心构建可以分为以下几类:
- 锁和信号量(semaphore)
- 原子(atomic)
- 阻塞队列(blocking queue)
- 锁存器(latch)
- 执行器(executor)

12.3.3 锁和自旋锁
12.4 并发库总结
12.4.1 java.util.concurrent中的lock
ReentrantLock是Lock的主要实现,主要使用了一个带int的compareAndSwap()。因此,在非争用的情况下,锁的获取是无锁的。这不仅可以极大提升在锁争用较少时系统的性能,而且还提供了支持不同加锁策略的额外灵活性。
