一.volatile:轻量级解决“线程安全”的方案
1.作用:
- 禁止指令重排序
- 解决线程可见性的问题,实现原理是当操作完变量之后,强制删除掉线程工作内存中的此变量。
注意事项:
volatile不能解决原子性问题。
synchronized 加锁和释放锁 [ JVM 层面的解决方案,自动帮我们进行加锁和释放锁 ]
Lock手动锁[程序员自己加锁和释放锁]
synchronized注意事项:
在进行加锁操作的时候,同一组业务一定是同一个锁对象。
1.synchronized实现原理:
(1.)操作:互斥锁mutex
(2.)JVM中:帮我们实现的监视器锁的加锁和释放锁的操作。
(3.)在Java层面中:
a)锁对象mutex .
b)锁存放的地方:变量的对象头
2.synchronized说明
synchronized锁机制是非公平锁。
公平锁可以按顺序进行执行,而非公平锁执行的效率更高。
在Java中所有锁默认的策略都是非公平锁。
(1) JDK 1.6之前是使用重量级锁实现的,性能非常低,所以用的并不多。
(2)JDK 1.6对synchronized做了一个优化(锁升级) :
优化过程:无锁—》偏向锁(第一个线程第一次访问)—》轻量级锁(自旋)—》重量级锁(停止自旋,并且把当前没有获取到锁的线程放到等待队列里)
3.synchronized的使用场景(3种) :
1)使用 sylnclchronized 来修饰代码块(加锁对象可以自定义)
2)使用synchronized 来修饰静态方法、( 加锁对象是当前的类对象)
3)使用synchronized 可以用来修饰普通方法
(加锁对象是当前类的实例)
lock手动锁
Lock默认的锁策略也是非公平锁,但是Lock可以显示的声明为公平锁。
注意事项:一定要把lock()放在try外面
(1)如果将lock()方法放在try里面,那么当try里面的代码出现异常之后就会执行finally里面的释放锁的代码,但此时加锁还没有成功
(2)如果将lock()方法放在try里面,执行finally里面释放锁的代码的时候就会报错(线程状态异常),释放锁的异常会覆盖掉业务代码的异常报错,因此增加了排除错误的成本
volatile和synchronized 有什么区别?
A:volatile可以解决内存可见性问题和禁止指令重排序,但volatile不能解决原子性问题; synchronized 用来保证线程安全,也就是synchronized 可以解决任何关于线程安全的问题(关键代码排队执行,始终只有一个线程会执行加锁操作;原子性问题,指定重排序问题,原子性问题 )。
2. synchronized和Lock之间的区别?
synchronized既可以修饰代码块,又可以修饰静态方法或者普通方法;而Lock 只能修
饰代码块。
synchronized只有非公平锁的锁策略,而Lock既可以是公平锁也可以是非公平锁
(ReentrantLock默认是非公平锁,也可以通过构造函数设置true 声明它为公平锁)。
ReentrantLock更加的灵活(比如tryLock试图获取锁) 。
synchronized是自动加锁和释放锁的,而ReentrantLock 需要自己手动加锁和释放锁。
————————————————
版权声明:本文为CSDN博主「月亮的兔耳朵」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_52012588/article/details/116725359