• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
小锅876
博客园    首页    新随笔    联系   管理    订阅  订阅
线程不安全能怎么办

一.volatile:轻量级解决“线程安全”的方案
1.作用:

  1. 禁止指令重排序
  2. 解决线程可见性的问题,实现原理是当操作完变量之后,强制删除掉线程工作内存中的此变量。
    注意事项:
    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

posted on 2022-09-19 11:25  小锅876  阅读(45)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3