java-多线程之-Volatile
Volatile用途:
1.线程可见性
2.防止指令重排序
3.dcl单例需要加Volatile吗?
double lock 后需要再加Volatile吗?
1.线程可见性
1.1 jmm对于内存的处理是4步:
1.从内存中把值读过来
2.对值进行修改
3.如果原来的这个内容没有别标记为 volatile,那么你对值的修改只是本地缓存。
4.如果有另一个缓存也读了这个,你的修改是不被看见的。
1.2.volatile 使用
子线程能否看到主线程里的flag?没加volatile
答案:肯定看不到
2.防止指令重排序
首先要明白cpu乱序执行是什么。
1.指令1 1.1去内存读数据
1.2返回数
2.指令2
1慢,2 快时,执行顺序,有可能1.1 -2 -1.1 这样执行,而不一定是1.1->1.2->2
前提:指令1 指令2 无因果关系
as if serial:在单线程里,无论是第二条先执行还是第一条先执行,最终结果是一样的。看上去像序列化,但不一定是。
3.dcl单例需要加Volatile吗?
double lock 后需要再加Volatile吗?
3.1对象创建
new 对象的时候有3条语句构成
1.new 在堆里申请了一块内存,大小: t对象的大小 ,m :=0 默认值
2.init 初始化 m:8
3.sdtore_i 建立连接 栈里的小t与内存建立链接
3.2单例
单例是一个类对象,只能有一个,不可能有第二次。有以下三个特点:
2.1构造方法:private
2.2使用单例 getInstance()
2.3 无论调用多少次,肯定都是一个对象。
我需要的时候才new
1.我定义,但不new
2.何时new ? 调用getInstance()时
多线程时,访问的时候并非同一个对象
如何解决?
double check lock 可以, 上锁前后都判空
DCL单例(Double Check Lock)到底要不要加volatile?
答案是肯定的。理由:
指令重排
原来是0-4-7
现在是0-7-4
thread2 使用了半初始化状态的对象 本想拿到8 现在拿到了0
所以还是要加的。
哇,终于写完了。这个看起来很容易,说清楚还是费了点事。