不可变对象模式
一.什么是不可变对象模式
不可变对象指的是,对象内部没有提供任何可供修改对象数据的方法,如果需要修改共享变量的任何数据,都需要先构建整个共享对象,然后对共享对象进行整体的替换,通过这种方式来达到对共享对象数据一致性的保证。
二.概念图
三.使用场景
1.被建模对象的状态变化不频繁
原因: 因为没改变一次,他就会创建一次相应对象,在变化频繁区域大量 使用会非常消耗性能
2.同时对一组相关的数据进行写操作,在不用锁的前提下,通过修改对象引用,使本来需要写两次的操作变成原子性操作
3.因为不可变对象的特性,符合map的key的不可变要求,所以不可变对象可以用作map的key
四. 设计要领
(一) 不可变对象(核心)------分清什么需要变什么不能变
-
用static volatile进行发布=======>实现线程安全
设计对应方法:
①get,set方法
-
不可变: 用final进行发布(想改变只能新建对象)=======>实现线程安全
设计对应方法:①:构造方法进行初始化
②:get方法
PS: 若是非基本数据类型对象get方法(具有防御性复制的方法)
如 map 转化成–>UnmodifiableMap
(二) 操作者(可有可无)------开启专用线程
- 任务:监听某个状态变量,一旦符合条件,立即对可变变量进行替换
五.难点思考
(一) 为什么 static volatile 的成员变量线程安全
Ø 进行对比分析:
- 明确: 对于类的成员变量是否线程安全, 看是否存在以下两点
①存在指令重排
②正在初始化,而其他线程却访问,获取到默认值
③.不具有可见性 - private n 会发生 ① 和 ② 和 ③
解决方案:
通过加static代码块,使其在类加载时初始化,可解决①②
通过volatile,解决 ③ - final n 线程安全
原因
①final禁止指令重排
②因为final修饰的成员变量,不会给他初始化默认值,第一次赋值就是我们设定的初始值, 所以其他线程要不就拿不到,一旦拿到,就是我们设定的初始值
③因为final字段不可变, JVM在第一次写,就写入主存