java中的锁




某个线程是否锁住同步资源

  • 悲观锁每次拿资源时候都认为会有人修改,在读数据的时候都会上锁,其他线程就会阻塞直到拿到锁。
  • 乐观锁是每次拿到数据的时候,都假设别人不会修改,都不会上锁。只有在更新数据的时候,去判断之前有没有线程更新了这个数据。如果这个数据没有更新过。当前线程就会将自己修改的线程成功写入。如果当前数据已经被更新了,当前线程要么自动重试,要么报错。

多个线程是否共享一把锁

  • 共享锁是指锁可以被多个线程持有,如果一个线程对数据加共享锁之后,那么其他线程只能对数据加共享锁,不能加独占锁。获得共享锁,只能读不能修改数据。JDK中,ReentrantReadWriteLock就是一种共享锁。
  • 独占锁指锁一次只能被一个线程所持有。如果一个线程对数据加排他锁后,该线程可以对数据读和写,其他线程不能对他进行任何操作。 JDK中的synchronizedJUC包中的Lock实现类都是独占锁。
  • 互斥锁是独占锁的一种形式。指一个资源同时只允许一个访问者对他进行访问。具有唯一性和排他性。互斥锁一次只能有一个线程拥有互斥锁。其他线程只能等待。
  • 读写锁是共享锁的一种具体体现,读写锁是管理一组锁,一个是只读的锁,一个是只写的锁,读锁在没写锁的时候被多个线程持有,写锁只能是独占的。写锁的优先级要高于读锁,一个获取了读锁的线程,一定要能看见前一个写锁更新的内容。读写锁相比于互斥锁并发的程度更高。
    JDK源码中定义读写锁接口ReadWriteLock。ReentrantReadWriteLock实现上述接口,支持锁降级不支持锁升级,可以由写锁降级为读锁。

多个线程竞争时是否要排队

  • 公平锁 : 按先后顺序排队,java中可以通过构造函数初始化构建公平锁。
  • 非公平锁:多个线程获取锁不是按照申请顺序来获得的,有可能后申请的线程比先申请的优先获得锁。可能会出现某个线程一直得不到锁的饥饿状态。Java中synchronized关键字就是非公平锁。ReentrantLock默认也是非公平锁

线程多个流程是否获取同一锁

  • 可重入锁:一个线程的多个流程能获取同一把锁,就是可重入锁。不能获取同一把锁,是不可重入锁。它是指同一个线程在外层方法获取了锁,在进入内层方法后自动获取锁。 ReentrantLock,Synchronized也是可重入锁。 使用可重入锁,从一定程度上可以避免死锁


在上图代码中,如果一个线程调用methodA,已经获取了锁,再去调用methodB就不用再次获取锁了。
如果使用不可重入锁,MethodB就可能不被当前线程执行,可能造成死锁。

某个线程锁住同步资源失败,是否不阻塞。

  • 如果某个线程锁住同步资源失败,但是希望这个线程不阻塞,就可以使用自旋锁或者自适应自旋锁。

  • 自旋锁:是指线程在没获取锁的时候,不被挂起,而是执行一个循环检查(这就是自旋)。 自旋的目的是减少被挂起的几率,线程的挂起和唤醒都是比价耗费资源的。如果锁的时间比较长,使用自旋锁还是会被挂起,自旋锁适合占用锁时间短的情况 AtomicInterger类就是自旋锁的操作。

  • jdk1.6后引入自适应自旋,自旋时间不固定,由前一次的上锁时间和锁拥有者的状态来决定的。如果虚拟机认为再次自旋很有可能成功,就继续自旋。成功不了,就直接挂起。

线程竞争同步资源时,细节流程是否发生变化的情况


jdk1.6后,为了减小获得锁和释放锁带来的消耗,引入四种锁的状态。

  • 当竞争升级,偏向锁会升级为轻量级锁。虽然竞争存在,但是理想情况下竞争的程度很低,所以通过自旋方式释放锁,等待上一个线程释放锁。如果线程的并发进一步加剧,自旋超过一定的次数或者一个线程持有锁,一个线程在自旋,如果再有第三个线程访问的时候,轻量级锁就会膨胀为重量级锁,除了当时拥有锁的线程之外的所有线程都阻塞,也就是变成了互斥锁(一个状态拿到锁,其余线程都处于阻塞状态)。synchronized关键字内部设计原理就是,这么一个锁升级的过程。

锁的再设计和优化的一些情况

  • 分段锁:是锁的一种再设计(不是具体的锁),将锁的粒度进一步细化,指针对数组中需要更新的一项进行加锁操作。比如CurrentHashMap的底层原理,使用的是分段锁Segment,就可以支持多线程并发操作了。

  • 锁优化

  • 锁粗化:

  • 锁消除 入下图,test()方法的三个变量,s1,s2和StringBuffer都是局部变量,存在于栈上,是线程私有的,所以多线程下是线程安全的,append(),方法是同步方法,而test本来就是安全的,所以虚拟机自动消除锁,这个过程叫做锁消除。

转载:https://www.bilibili.com/video/BV1ug411a7Jb/?vd_source=46d50b5d646b50dcb2a208d3946b1598

作者:静默虚空
欢迎任何形式的转载,但请务必注明出处。
限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。

posted @   Chenyi_li  阅读(78)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 易语言 —— 开山篇
· 实操Deepseek接入个人知识库
· Trae初体验
历史上的今天:
2021-10-14 unity商店下载地址
点击右上角即可分享
微信分享提示