Java 内存模型
JMM: java memory model (java 内存模型)
抽象的内存模型--不存在;
volatile :
保证可见性,不保证原子性(synchronized 保证),
禁止指令重排-(不让插队--保证有序)
所以就是 volatile 的 java 虚拟机的轻量级的同步机制
一、可见性
若是某一个线程改变了一个固定的变量,其他线程会立刻知晓;
也就是及时通知
//volatile 可以保证可见性:
及时的通知其他线程,主物理内存中的值已经被修改;
import java.util.concurrent.TimeUnit;
class volatileTest1{
}
public class volatileDemo {
}
2.不保证原子性:
volatile 支持可见性--;
原子性: 与 mysql 事务中的类似,不可分割,完整性,
也即是某个线程在工作时,中间不可以加塞和分割,要么整体同时成功,要么失败;
原子性:--丢数据的形式;基本是没可能;
a++不能保证原子性; volatile 不能保证原子性;
丢失数据的原因:
细说 a++的运行过程:
分为三步;
①读取,从主物理内存中的 a----》拷贝到本地的线程的工作内存;
②加一:
③写回主内存同步数据
不保证原子性就是--可能会在线程操作的过程中会有数据抢占;
随时可能会被打断;
不保证原子性--就会出现写覆盖的情况;--
怎么解决 volatile 的不保证原子性情况:
①加 synchronized 的同步机制锁(太重啦)
注意:atomicInteger 的底层就是 Cas 的;
②juc 中的 atomic 包中的一个 atomicInteger 的类
a++;
方法是一个
atomicInteger.getAndIncrement(); //每次加 1-保证原子性的加 1
//底层就是 CAS 的; atomicInteger.getAndIncrement()
//解决的是 volatile 不保证原子性的 AtomicInteger
//AtomicInteger 是 java.util.concurrent.atomic 原子包写的类 AtomicInteger atomicInteger=new AtomicInteger();
public void addMyatomic(){
atomicInteger.getAndIncrement(); //每次加 1-保证原子性的加 1
/*** Atomically increments by one the current value.*原子性增加 1* @return the previous value*//public final int getAndIncrement() {return unsafe.getAndAddInt(this, valueOffset, 1);}/
}`
`package com.atguigu;
import com.sun.org.apache.xpath.internal.operations.Variable;
import javax.lang.model.element.VariableElement;import java.util.concurrent.atomic.AtomicInteger;
class VolatileTest2{//资源类
volatile int a; //全局变量的默认为 0
public void addPlusPlus(){
}
//解决的是 volatile 不保证原子性的 AtomicInteger
//AtomicInteger 是 java.util.concurrent.atomic 原子包写的类 AtomicInteger atomicInteger=new AtomicInteger();
public void addMyatomic(){
atomicInteger.getAndIncrement(); //每次加 1-保证原子性的加 1
/*** Atomically increments by one the current value.*原子性增加 1* @return the previous value*//public final int getAndIncrement() {return unsafe.getAndAddInt(this, valueOffset, 1);}/
}
}
public class VolatileNoAtomic {
//volatile 不保证原子性的小李子
public static void main(String[] args) {
for(int i=1;i<=30;i++) {
}
//3.main 线程是在 a++之中有感知的,
}
}`
三、禁止指令重排序(保证有序的执行)
四、面试:在哪些场景下遇见 volatile?
单例模式:
我们所写的简单经典的:
class SingletonTest {//静态的空对象 private static SingletonTest Instance=null;
}
public class SingletonTest1 {
//多线程
for(int i=1;i<10;i++) {
}
}
这个测试环境是在: mian 线程中只有简答的线程调用的;
2.单例模式的 DCL(double check Lock)双端检锁机制---》可重复锁
解决
public static SingletonTest02 getSingletonTest(){
DCL---可能不安全.因为存在的是一个指令重排的过程
这里我们用的是 volatile 的解释;
但是 DCL:不能保证是绝对安全的所以;
在单例的这个对象前面加入 volatil
//volatile 的作用是禁止重排序 private static volatile SingletonTest02 Instance=null;
版权声明: 本文为 InfoQ 作者【卢卡多多】的原创文章。
原文链接:【http://xie.infoq.cn/article/48435317d83371ac432926b00】。文章转载请联系作者。
评论