身为JAVA工作者必须了解的实战知识(二)
一、可见性
什么是可见性?
Java线程安全需要防止某个线程正在使用对象状态而另一个线程在同时修改该状态,而且需要确保当一个线程修改了对象的状态后,其他线程可以看到发生的状态变化。 后者就是可见性的描述即多线程可以实时获取其他线程修改后的状态。
*** 待补充 两个工人同时记录生产产品总数问题
1. 失效数据
可见性出现问题就是其他线程没有获取到修改后的状态,更直观的描述就是其他线程获取到的数据是失效数据。
2. 非原子64位操作
3. 加锁与可见性
例如在一个变量的读取与+1上添加一把锁,锁保证了其他线程获取到此变量都是+1后的值,所以可以保证可见性。
4. Volatile变量
线程对共享变量的修改,对其他线程可见
满足以下条件,使用Volatitle:
对变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程更新变量的值。
该变量不会与其他状态变量一起纳入不变形条件中。
在访问变量时不需要加锁。
二、发布 、逸出
发布一个对象的意思是指,使对象能够在当期作用域之外的代码中使用。
简单的可以理解为其他地方获取到当前类的对象,这种情况就是发布当前类。
Java多线程不仅要确保当前类是线程安全的,而且需要保证使用当前类对象的所有地方都要保证线程安全性。
三、封装
线程封闭 - 把共享的数据,仅在线程中使用,不共享.例如java的ThreadLocal类
Ad-hoc线程封闭 -- 维护线程封闭性的职责完全由程序实现承担.(很脆弱)
线程封闭 - 通常将特定子系统实现为一个单线程子系统
栈封闭
线程封闭的特例, 例如基本类型的局部变量
ThreadLocal - 通常防止可变的单实例对象 或 全局变量进行共享.
四、不可变
final对象,本身不可改变,但是final中的变量却可以改变
五、安全发布方式:
1. 静态初始化函数中初始化一个对象引用
2. 将对象的引用保存到volatile类型的域或者AtomicReference对象中
3. 将对象的引用保存到某个正确的构造对象的final类型域中
4. 将对象的引用保存到一个由锁保护的域中
一、同步容器类