Lock与Synchronized底层问题讨论

2 篇文章 0 订阅
1 篇文章 0 订阅

一、为什么分布式环境下synchronized失效? 因为不同服务属于不同进程

synchronized:底层是通过moniterrenter\moniterexit指令来完成,JVM需要保证每一个monitorenter都有一个monitorexit与之相对应

使用:

  1. 修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁。
  2. 静态方法,作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁。
  3. 修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁。

image.png

作用:解决并发编程中存在的原子性、可见性和有序性问题

  • 原子性:一个操作是不可中断的,要么全部执行成功要么全部执行失败
  • 可见性:当一个线程修改了共享变量后,其他线程能够立即得知这个修改(synchronized、volatile修改值后都会将共享变量同步到主内存中)
  • 有序性:指执行代码是有序的去执行,线程1先执行,完了之后线程2才去执行(因为JAVA中允许重排序只要不改变执行结果,数据之间不存在依赖)比如:instance = new Singleton(); 1.分配对象的内存空间;2.初始化对象;3.设置instance指向刚分配的内存地址,如果2、3重排,那么并发时候判断instance 是否== null,就会出现错误判断 (synchronized 只是保证了代码执行的有序性,并没有保证不能编译器指令不会重排)

缺点:

  • 不可中断
  • 性能较差(看看后面是怎么改进的)

特性

  • 可重入:指的是同一线程的外层方法获得获得锁之后,内层方法可以直接在此获取该锁
  • 不可中断:一旦这个锁已经被别人获得了,如果我还想获取,我只能选择等待或者阻塞,直到别的线程释放这个锁(返回或者抛异常).如果别人永远不释放锁,那么我只能永远地等下去
      相比之下,Lock类,可以拥有中断的能力,
        第一点:如果我觉得我等的时间太长了,有权中断现在已经获取到锁的线程的执行,
        第二点:如果我绝得我等待的时间太长不想再等了,也可以退出.
  • 不需要手动释放

二、为什么有了synchronized 还需要volatile

  • 一方面是因为synchronized是一种锁机制,存在阻塞问题和性能问题,而volatile并不是锁,所以不存在阻塞和性能问题
  • volatile 禁止重排的功能,不可替代 (synchronized 只是保证了代码执行的有序性,并没有保证不能编译器指令不会重排)

三、为什么volatile不能保证原子性

  • 因为定义一个volatile变量后,如果此变量在多线程情况下执行类似像i++这种不是原子操作, 会导致最终值不对。比如当 i=5 的时候A,B两个线程同时读入了 i 的值, 然后A线程执行了 temp = i + 1的操作, 要注意,此时的 i 的值还没有变化,然后B线程也执行了 temp = i + 1的操作,注意,此时A,B两个线程保存的 i 的值都是5,temp 的值都是6, 然后A线程执行了 i = temp (6)的操作,此时i的值会立即刷新到主存并通知其他线程保存的 i 值失效, 此时B线程需要重新读取 i 的值那么此时B线程保存的 i 就是6,同时B线程保存的 temp 还仍然是6, 然后B线程执行 i=temp (6),所以导致了计算结果比预期少了1。

四、volatile和synchronized的区别

  1. volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取; synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
  2. volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的
  3. volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性
  4. volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
  5. volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值