并发编程——可见性和有序性的解决办法

目录

volatile 禁用缓存

Happen-before原则 

final关键字

缓存和编译优化造成了可见性和有序性的问题,通过 java内存模型 来解决 可见性 和 有序性 问题。解决该问题的合理方案是提供一种方法可以让程序员可以按需禁用缓存和编译优化。

java内存模型是一套规范,从程序员角度来看,Java 内存模型规范了 JVM 如何提供按需禁用缓存和编译优化的方法。这些方法,包括volatilesynchronized final三个关键字,以及六项happen-before原则

我们常说的 JVM内存模型 指的是JVM的内存分区;而Java内存模型是一种虚拟机规范。

volatile 禁用缓存

用volatile声明的变量不使用CPU缓存都从内存中读入或者写入

但是在1.5以前的版本中,存在一个问题,如下代码:

可以看出 变量 v 是禁用了缓存,那么当v等于true的时候,内存中的X是多少呢,可能是42 也可能是 0,因为无法保证使用了缓存的x是否将值已经写入了内存。1.5版本以后这个问题就解决了,通过 happen-before原则 对 volatile语义 进行了增强,保证了当v为true的时候x一定是42。

Happen-before原则 

A happen-before B 的意思是:A的操作结果对后续的操作B是可见的。可见指的是对于共享变量的修改。

1、程序的有序性
      按照程序编写的顺序,前面的操作happen-before于后面的操作。
及对于以上代码,从程序顺序上来讲,x=42 happen-before v = true;

2、volatile变量规则 
     对于一个volatile变量的写操作happen-before于对这个变量的读操作。

3、传递性
      如果 A happen-before B 且  B happen-before C,则可以推出 A happen-before C。

单独看以上三条结论,将x变量写成42 是对 将 v 变量写成 true 是可见的(来自第一条)
                                    对于 v 写成 true 对于 读取 v 的时候是可见的 (来自第二条)
                                    所以 将x的值为42 对于 读取 v 也是可见的 (来自第三条)
这也就是对于volatile语义的增强。

4、管程中锁的规则 (java中指的就是synchronized
      一个锁的解锁操作 happen-before  于后续对于这个锁的加锁操作。     
      
    如果线程A将对this进行加锁,将x从10变成了12,那么线程B再对this进行加锁的时候,x=12对线程B是可见的。

5、线程 start() 规则
      当父进程启动了一个子进程的时候,父进程中的操作 happen-before 于子进程中的所有操作。

       

6、线程 join() 规则
      父进程等待子进程执行,子进程执行完成以后,子进程中的操作 happen-before 于父进程。

      

final关键字:

  • 修饰类:指的类不可以被继承
  • 修饰变量:变量初始化后值不可以被改变
  • 修饰常量:常量会被放进常量池中
  • 修饰方法:该方法不可以被子类重写

参考文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值