java锁 -笔记

  • java线程阻塞的代价 (理解java中各种锁的优缺点的基础)

    • java的线程是映射到操作系统原生线程之上:阻塞或唤醒线程->操作系统介入->在户态与核心态之间切换

    这种切换会消耗大量的系统资源,因为用户态与内核态都有各自专用的内存空间,专用的寄存器等,用户态切换至内核态需要传递给许多变量、参数给内核,内核也需要保护好用户态在切换时的一些寄存器值、变量等,以便内核态调用结束后切换回用户态继续工作。

    • 线程状态切换是高频操作时,会消耗很多CPU处理时间;
    • 对于需要同步的简单的代码块,获取锁挂起操作消耗的时间>用户代码执行时间

    synchronized会导致争用不到锁的线程进入阻塞状态,所以说它是java语言中一个重量级的同步操纵,被称为重量级锁,为了缓解上述性能问题,JVM从1.5开始,引入了轻量锁与偏向锁,默认启用了自旋锁,他们都属于乐观锁。

    引自:https://www.cnblogs.com/linghu-java/p/8944784.html

  • 乐观锁&悲观锁

    • 乐观锁:认为读多写少
      • 实现思路:比较跟上一次的版本号,如果一样则更新(redis也是,写操作更新版本)
      • CAS 实现:CAS是一种无锁算法,CAS有3个操作数,内存值V,旧的预期值A,
        要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值
        V修改为B,否则什么都不做
    • 悲观锁:认为写多,遇到并发写的可能性高 Synchronized、RetreenLock
    • AQS框架下的锁:先尝试cas乐观锁去获取锁,获取不到,才会转换为悲观锁
  • 自旋锁

    • 内核态和用户态之间的切换进入阻塞挂起状态->线程只需要等一等(自旋,占用CPU做无用功)
    • 适用场景:锁的竞争不激烈,且占用锁时间非常短
    • 自旋的周期:避免自旋执行时间太长,自旋状态占用 CPU 资源
  • 可重入锁(递归锁)

  • ReadWriteLock 读写锁

    • 读锁
      代码只读数据,可以很多人同时读,但不能同时写,那就上读锁
    • 写锁
      如果你的代码修改数据,只能有一个人在写,且不能同时读取,那就上写锁。
    • 接 口 java.util.concurrent.locks.ReadWriteLock 具 体实现:ReentrantReadWriteLock
  • 共享锁&独占锁

    • 独占锁:每次只能有一个线程能持有锁,如Reentrantlock

      悲观保守的加锁策略,它避免了读/读冲突(并不会影响数据的一致性,限制了不必要的并发性)

    • 共享锁:乐观锁,允许多个线程同时获取锁(放宽了加锁策略)

      java 的并发包中 ReadWriteLock(读-写锁)它允许一个资源可以被多个读操作访问,或者被一个写操作访问,但两者不能同时进行

  • 重量级锁&轻量级锁

    • 重量级锁 ( Mutex Lock ):
      • 底层的操作系统的 Mutex Lock -> 监视器锁(monitor)->Synchronized (->实现)
      • 操作系统实现线程之间的切换,需要从用户态转换到核心态
      • 重量级锁:这种依赖于操作系统 Mutex Lock 所实现的锁
    • 轻量级锁
      • 锁的状态(4种):无锁状态、偏向锁、轻量级锁和重量级锁 (锁的升级是单向的,->)
      • 应用场景?:线程交替执行同步块
      • 不适用场景?:同一时间访问同一锁,则轻量级锁膨胀为重量级锁
  • 偏向锁

    • 适用场景:始终只有一个线程在执行同步块,锁无竞争

      一旦有竞争就升级为轻量级锁,撤销偏向锁,导致stop the word操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值