volatile、Synchronized与final一些理解

volatile:

    使用volatile修饰的共享变量在写操作的时候会多出Lock指令,会立即引发两种效果:

  1. 将当前变量的值从工作内存写会到主内存中
  2. 其他CPU里面缓存的该变量的值会置为无效(由缓存一致性协议保障)

---- 锁缓存的开销比锁总线的开销要少很多,锁总线意味着不能访问系统内存!

3.禁止读和写的重排序 – 双重锁问题就是通过这个解决的!(第一个操作是volatile写(A),第二个操作是volatile读/写(B),不能重排序)

 

Synchronize:

    一般有三种使用方式:

  1. 普通方法 – 锁的是当前对象(对象锁)
  2. 静态方法 – 锁的是class对象 (类锁)

---- 一个类不管被new多少次,静态变量/方法在内存中都只有一个份!

      3.静态代码块 – 锁的是代码块里的资源

    编译的字节码中会多出monitorent/momitorexit指令,它们修饰之间的内容会被视为锁定,线程拥有对象对应的monitor才能执行指令之间的代码.

    个人的感觉是,在如今synchronized进行了大量优化之后,volatile几乎很少使用,使如果使用到volatile要特别注意它的语义

 

final: 语义是在处理器中实现的

final的用法一般有一下几种:

  1. 用来修饰数据,包括成员变量和局部变量,该变量只能被赋值一次且它的值无法被改变。对于成员变量来讲,我们必须在声明时或者构造方法中对它赋值;
  2. 用来修饰方法参数,表示在变量的生存期中,参数的值不能被改变;
  3. 修饰方法,表示该方法无法被重写;
  4. 修饰类,表示该类无法被继承。

    final在同步中的作用会经常被忽视,实际上final可以做出如下保证:

   当创建一个对象时,使用final关键字能够使别的线程不能访问到处于”部分创建”的对象。保证对象的安全发布,即不会出现对象创建到一半,别的线程就拿着这个引用去乱用。

 

final域对于编译器和处理器来说有两个重排序规则:

  1. 写: final域写入和对象引用赋值这两个操作不能重排序 – 保证创建的顺序性
  2. 读: 初次读对象的引用和里面的final域不能重排序 – 保证读的顺序性
  1. 避免一个对象的引用被两个线程持有,然后一个线程读,一个线程写,不用final可能会出现脏读的情况

 

注意: final无法解决双重锁问题,因为双重锁问题的问题在于B线程拿到引用实际上没有被A线程完全初始化完毕,此时还没有操作到对象里面的变量.

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值