程序等待某个同步IO操作完成,CPU将处于空间状态。
线程安全---多个线程交替访问某个类,调用方不需做任何的同步,这个类始终表现出正确的行为
- 不共享变量
- 变量是不可变
- 访问变量使用同步
synchronized除了实现原子性(确定临界区),保证了内存可见性(一个线程修改了变量后,其他线程能够看到)
14章
sleep进入休眠,但有可能这是不必要的
忙等待,消耗过多的CPU时钟
Thead.yield给调度器一个提示,让出一定的时间给另一个线程运行
一般是二选一,第三个感觉不靠谱,有平台相关性。sleep抛异常,yield不抛
优先使用notifyAll(虽然效率低一些,但容易保证准确),同时满足才能使用notify
等待线程的类型都相同
每次通知只能唤醒一个线程
synchronized、reentrantlock区别
reentrantlock有公平锁、非阻塞(防止死锁)、可以绑定多个条件
AQS只可能在一个地方阻塞,通过CAS实现
15章
通过原子变量和非阻塞的同步机制提高性能和可伸缩性,将发生竞争的范围缩小到单个变量上,粒度更细
Java的锁(例如重入锁)语法简洁,但实现不简单,至少需要一次CAS
CAS缺点:调用者自己处理竞争问题(重试、回退、放弃),锁能自动处理(线程在获得锁之前一直阻塞)
如果操作系统不支持CAS,JVM将使用自旋锁
在中低程序的竞争中,原子变量提供更高的可伸缩性。高强度的竞争中,锁能有效避免竞争。
当交通更拥堵,信号灯能实现更高的吞吐量,低拥堵的时候,环岛能实现更高吞吐量
创建非阻塞算法的关键在于找出如何将原子修改的范围缩小到单个变量,维护数据的一致性,CAS+volatile
JDK升级提到的性能提升主要来自于非阻塞算法的应用
16章
在共享内存的多处理器架构中,每个处理器都有自己的缓存,定期与主存同步
内存屏障---强制刷新缓存
Happens-Before---两个操作如果缺少Happens-Before关系了,JVM会重排序(同步解决)
Happens-Before规则
监视器锁规则:在同一个监视器锁上,解锁操作在加锁操作之前执行
DCL要使用volatile
初始化安全性---含有final域的对象,可以防止对象的初始引用被重排序到构造过程之前。
不是final域,或者存在除构造函数以外的其他方法能修改