目录
1可见性
synchronized不仅仅用于实现原子性或者确定“临界性”,还用于"内存可见性"。
内存可见性可以通过显式同步或类库中内置同步实现。
重排序会导致输出0
也可能因为可见性ready一直读不到true,无限循环
1.1失效数据
1.2非原子64位操作
- 最低安全性:
- 例外:非volatile类型64位变量(double,long)
1.3加锁与可见性
1.4volatile变量
优点:避免加锁,开销低
缺点:可见性比加锁弱(待补充),难理解,不保证原子性
2.对象发布与逸出
解释:
Java中,内部类对象持有指向外部类对象的引用。
所以在构造函数中使用内部类导致this逸出。
2.1this逸出
- 除了上述在构造函数中使用内部类导致this逸出外,在构造函数中使用启动线程也会导致this逸出。
- 解决方案:
3.线程封闭
线程封闭:只在单线程内访问数据,无需同步。
3.1Ad-hoc线程封闭
3.2栈封闭
栈封闭(也被称为线程内部使用或者线程局部使用)比Ad-hoc线程封闭更易于维护,也更加健壮。
Java语言确保了基本类型的局部变量始终封闭在线程内。
下面代码是表示:基本类型的局部变量与引用变量的线程封闭性。
3.3ThreadLocal
4.不变性
4.1final域
https://juejin.im/post/6844903601068998664
写final域的重排序规则:禁止对final域的写重排序到构造函数之外
读final域重排序规则为:初次读对象引用和初次读该对象包含的final域,JMM会禁止这两个操作的重排序。
保证一旦你得到了引用,final域的值都是完成了初始化的
4.2使用volatile类型来发布不可变对象
如果不使用不可变对象,初始化安全性不能保证。