synchronize和volatile的区别

前言

面试的时候经常被问到synchronized与volatile的区别,你可能会奇怪他俩有什么关系吗,如果觉着关系不大,但是又不能直接说,只能回答他们的共性和区别就ok了。
说到这个两个,那就不得不先说一下线程的安全保证

多线程只有保证如下基本特性时才能保证安全:

可见性:线程都是基于cpu的运算,cpu有缓冲区,所以每次在计算的时候都会把数据加载到缓冲区中计算,那计算好的数据最终被会写到主存中,但是有时间差,没有synchronized或者volatile修饰,那么下一个线程读取的时候,读到的数据就有可能是修改前的数据。加上synchronized或者volatile,在该线程释放的时候会把数据写回主存。
主存简单理解为,内存的堆区,声明的属性或new的对象大部分都在堆中。

原子性:就好比你在思考一件事情,不愿意被其他事情打扰一样,线程的原子性也是如此,在执行一段逻辑的时候,也不希望被其他线程干预。多个线程同时请求同一资源或者代码块,这时候对资源或者代码加上synchronized,表示此时只有一个线程能够拿到锁,其他线程只能等待它被释放才能进行下一轮争夺。

有序性:处理器为了提高程序运行效率,可能会对输入代码进行优化,所以有可能会调整语句的执行顺序,但是它会保证最终结果的正确性。这种正确性只保证单线程里是没问题的

synchronize主要特性

上述三个都有:
可见性
原子性
有序性

volatile主要特性

可见性
有序性(禁止指令重排序)

还没完,看到synchronizevolatile大家都会想到一个设计模式吧,那就是单例模式,那既然synchronize保证的上述三点,为啥单例模式中还要用volatile修饰变量呢?

synchronize:保证原子性、可见性、有序性(多线程顺序执行)

volatile:保证可见性、有序性(禁止指令重排序)
其实这个有序性,一个是保证了多线程执行顺序,一个保证的是指令重拍,很多人都把synchronize的有序性理解错了。

接下来具体跟大家介绍一下单例模式中的两个有序性。

有序性

synchronize只能保证多线程串行执行加锁部分的代码块,但是他不能保证指令执行的顺序,单例模式中锁住的代码块是是一个实例化的过程,那就涉及到指令重拍的问题了。
实例过程:

  1. 创建内存
  2. 初始化对象
  3. 对象指针指向创建的内存

volatile:如果把实例化的3和2顺序颠倒,线程执行完步骤3给对象分配了地址,但是此时线程还没执行2初始化对象,就会导致其他线程拿到实例的对象出错。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值