原子性、有序性、可见性

一、原子性是指一个操作是不可中断的,要么全部执行成功要么全部执行失败,有着“同生共死”的感觉。及时在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程所干扰。

像是a++  并不是原子操作,因为a++其实包括,读取a的值,将a的值加1,将结果赋值给a

那么java内存模型中定义了8种原子方法,这8中方法也不能再拆分

 1.lock(锁定)用于锁定主内存中变量,将他变成一个线程独占的状态

 2.unlock(解锁)用于解锁变量被单线程独占的状态

 3.read(读取),用于主内存中的变量,读取到工作内存中,以便load动作使用

 4.load(加载),将read读取的内容放入变量副本中。

 5.use(使用),将工作内存中的变量值,传递给执行引擎,

 6.assign(赋值) 把从执行引擎传来的值,赋值给工作变量

 7.store(存储) 将工作内存中的变量,传递给主存,以便于后面wirte的使用

 8.write(写) 将它把store操作从工作内存中得到的变量的值放入主内存的变量中

注意:java内存模型只是保证他们每个操作是原子性的

由原子性变量操作read,load,use,assign,store,write,可以大致认为基本数据类型的访问读写具备原子性(例外就是long和double的非原子性协定)

 

将一个变量从主内存中放到线程内存中,需要使用read和load操作,线程内存中的值放入主内存中,需要使用store和write操作

其中六条可以满足基本数据类型的访问读写具备原子性,还剩下lock和unlock两条原子操作。如果我们需要更大范围的原子性操作就可以使用lock和unlock原子操作。尽管jvm没有把lock和unlock开放给我们使用,但jvm以更高层次的指令monitorenter和monitorexit指令开放给我们使用,反应到java代码中就是---synchronized关键字,也就是说synchronized满足原子性

二、有序性

  在单例模式的实现上有一种双重检验锁定的方式(Double-checked Locking),我们知道在创建对象时,其实是三步操作

                instance = new Singleton();

 1.为对象份分配内存空间,2.创建对象,3.对象指向内存空间

那么我们的jmm在满足happend-before规则的情况下,允许处理器进行指令重排序,也就是说在不影响结果的情况下,可以进行指令重排序, 1 2 步执行的先后顺序,对结果没有影响,因此可以发生指令重排序,当AB 线程方式访问时,可能A在执行了

   instance = new Singleton(); 操作后,释放了锁,释放锁以后,先执行的如果是创建对象,那么B在获得锁以后,也会导致判断不为null的情况。

三、可见性

 

可见性是指当一个线程修改了共享变量后,其他线程能够立即得知这个修改。通过之前对synchronzed内存语义进行了分析,当线程获取锁时会从主内存中获取共享变量的最新值,释放锁的时候会将共享变量同步到主内存中。从而,synchronized具有可见性。同样的在volatile分析中,会通过在指令中添加lock指令,以实现内存可见性。因此, volatile具有可见性

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值