volatile和synchronized

volatile和synchronized这两个关键词的作用和原理面试的时候经常会被问到,那么我们今天就放在一起聊聊这两个关键词

volatile关键词

我们说volatile前我们先一起回归下java的内存模型
从下面的内从模型中我们可以看到每个线程均拥有自己独立的内存
两个线程如果要通信也要经历两个步骤:
1、线程A从主内存中copy共享变量副本存入自己的内存中,进行操作,然后把更新后的变量刷新到主内存中
2、线程B从主内存中copy主内存中更新后的变量值
在这里插入图片描述
基于以上的线程通信的原理,在并发情况下会出现线程安全的问题。
下面我们就来说volatile ,volatile关键词有两个作用:
1、可以保证多线程环境下,共享变量的可见性
2、通过增加内存屏障的方式防止指令重排
注:volatile是不能保证多线程环境,共享变量的原子性
那我们再分开说明下volatile是如何实现可见性和禁止指令重排的
可见性:
1、相较于普通变量,修改volatile变量时,会强制将修改后的值刷新到主内存中
2、同时修改volatile变量会将其他线程工作内存中的共享变量副本置为无效,再此读取工作内存中这个变量时由于已经无效,就会重新从主内存中读取新的值进来
由此两步,可保证变量在多线程环境下的可见性
禁止指令重排
上面我们说过volatile是通过内存屏障保证禁止指令重排的。那么什么是内存屏障呢?
内存屏障(英语:Memory barrier),也称内存栅栏,内存栅障,屏障指令等,是一类同步屏障指令,它使得 CPU 或编译器在对内存进行操作的时候, 严格按照一定的顺序来执行, 也就是说在memory barrier 之前的指令和memory barrier之后的指令不会由于系统优化等原因而导致乱序。内存屏障并不是JVM发明或者独有的概念,而是操作系统中的概念,JVM为了屏蔽不同操作系统对内存屏障实现的差异,提供了四类内存屏障指令:
在这里插入图片描述
在每个volatile写操作的前面插入一个StoreStore屏障。
在每个volatile写操作的后面插入一个StoreLoad屏障。
在每个volatile读操作的前面插入一个LoadLoad屏障。
在每个volatile读操作的后面插入一个LoadStore屏障
通过以上的策略,实现禁止指令重排

synchronized关键词

Synchronized底层是使用monitor实现的,他采用互斥的方式保证同一时刻一个monitor对象锁智能有一个线程拥有,其他线程要想获取对象锁需在阻塞队列中等待。
synchronized修饰普通方法,锁对象默认为this
synchronize修饰静态的方法或指定锁对象为Class对象
synchronize修饰的方法不管方法是否执行成功,最后都会释放对象锁
synchronize加锁和释放锁过程
如下一个class文件
在这里插入图片描述
Monitorenter和Monitorexit指令,会让对象在执行,使其锁计数器加1或者减1。每一个对象在同一时间只与一个monitor(锁)相关联,而一个monitor在同一时间只能被一个线程获得,一个对象在尝试获得与这个对象相关联的Monitor锁的所有权的时候,monitorenter指令会发生如下3中情况之一:
monitor计数器为0,意味着目前还没有被获得,那这个线程就会立刻获得然后把锁计数器+1,一旦+1,别的线程再想获取,就需要等待
如果这个monitor已经拿到了这个锁的所有权,又重入了这把锁,那锁计数器就会累加,变成2,并且随着重入的次数,会一直累加
这把锁已经被别的线程获取了,等待锁释放
monitorexit指令:释放对于monitor的所有权,释放过程很简单,就是讲monitor的计数器减1,如果减完以后,计数器不是0,则代表刚才是重入进来的,当前线程还继续持有这把锁的所有权,如果计数器变成0,则代表当前线程不再拥有该monitor的所有权,即释放锁。
与lock的区别
1、synchronized不需要手动释放锁,lock需要在锁用完后进行unlock;
2、synchronized只能是默认的非公平锁,lock可以指定使用公平锁或者非公平锁;
3、lock提供的Condition(条件)可以指定唤醒哪些线程,而synchronized只能随机唤醒一个或者全部唤醒;

  • 16
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值