多线程补充

  1. cas

    • CompareAndSwap(比较并交换)
      • 原理:旧的预期值A,当前值V,要更新的值B,当且仅当V=A的时候才去更新B
        • 类似于数据库的乐观锁机制
      • 保证比较和交换两个步骤是原子性:调用底层c的同名方法,完成对操作系统的访问,在硬件层面保证比较和交换两个操作是原子操作。
    • 缺陷:
      • 循环时间较长
        • LongAddr(后面讲)
        • 控制自旋次数,如果自旋次数过多就将线程挂起。
      • 只能对一个变量进行cas操作保证原子性,不能同时对多个变量cas
        • 只能加锁解决
      • ABA问题
        • 值从A到B再到A,外部看起来没有发生变化,如果一个线程在最开始读到A,那么它的cas操作可以成功,在某些情况下,这不是我们想要的结果
          • 条件比较苛刻:主要值发生过变化,本次操作就必须失败->需要处理
          • 条件比较宽松:值只要不变,本次操作就可以成功->不需要考虑这个问题
        • 解决方案:加版本号解决,和数据库乐观锁的道理是一样的。
  2. atomic原子包

    1. 基本类型
      1. AtomicInteger
      2. AtomicLong
      3. AtomicBoolean
      4. 总结:
        1. api的特点
          1. 如果get在前就是获取修改之前的值
          2. get在后就是获取修改之后的值
    2. 引用类型
      1. AtomicRefrence
        • 引用类型原子类,比较的是实例的内存地址
      2. AtomicStampleRefrence
        • 带整形的版本号的引用原子类
        • 必须值和预期值相等,版本号和预期版本号相等才能修改值为更新值,版本号为更新版本号
      3. AtomicMarkbleRefrence
        • 带boolean类型的版本号的引用原子类
        • 必须值和预期值相等,版本号和预期版本号相等才能修改值为更新值,版本号为更新版本号
    3. 基本类型数组
      1. AtomicIntegerArray
      2. AtomicLongArray
      3. AtomicBooleanArray
      4. 总结:
        • 和基本类型比较来看,第一个参数是下标,后面都一样
    4. 引用类型数组
      1. AtomicRefrenceArray
    5. 属性修改器
      1. AtomicLongUpdater
      2. AtomicIntegerUpdater
      3. AtomicRefrenceUpdater
      4. 注意:
        1. 要修改的属性不能是static,因为static不能通过unsafe拿到内存地址偏移量
        2. 要修改的属性不能final,因为final不能修改
        3. 要修改的属性必须是对修改器所在区域是可见的才可以
        4. 要修改的属性必须通过volatile修饰,保证属性本身是读一致的。
    6. jdk8新增类
      1. LongAdder
      2. DoubleAdder
      3. LongAccumulator
      4. DoubleAccumulator
      5. 总结:
        • LongAdder对比AtomicLong来说是将一个变量值拆分为一个数组,这样尽可能少的线程去竞争修改同一个变量,减低对单个值的并发量,降低总自旋次数,降低响应时间,提升执行效率。
  3. AQS队列同步器

    • 是一个抽象类,构建同步组件的基础框架,内部定义了一系列模板方法
      • acquire:独占式的获取资源
      • acquireShared:共享方式获取资源
    • 有一些未实现的方法,交给子类实现
      • tryAcquire:同步组件自定义获取资源的方式
      • tryAcquireShared:同步组件自定义获取共享资源的方式
    • 原理:
      • state:用来描述资源状态,当一个线程获取到资源(成功修改了资源状态),就正常执行,如果获取失败了,就将当前线程入队
      • CLH同步队列:用来保存获取不到资源的线程,当前一个线程执行完毕之后会唤醒后继节点继续执行
      • 模拟场景:第一个获取到资源的线程执行完毕了,它不在队列中,如何唤醒后继节点的
      • 出队入队:
        • 入队:当线程获取不到资源就入队
        • 出队:前一个线程执行完毕了,唤醒队列中头部节点的后面离头部节点最近的正常节点对应的线程。
  4. juc之锁

    1. ReentrantLock
      1. 特性
        1. 具备公平性
        2. 可重入性
        3. 互斥性
      2. 实现了Lock接口,可以通过lock()加锁,unlock解锁
      3. 内部维护一个队列同步器的实现类sync
        1. 加锁:获取state资源的过程,如果获取到了(修改成功),就表示加锁成功,继续执行
        2. 解锁:释放state的过程,每unlock一次,state状态-1,减到0表示资源释放完毕,其他线程可以获取锁
    2. ReentrantReadWriteLock
      1. 特性
        1. 具备公平性
        2. 可重入性
        3. 读不互斥,写互斥,读写互斥
      2. 内部一把读锁,一把写锁,都实现了lock接口
      3. 内部维护一个队列同步器的实现类sync
  5. Condition

    1. 作用和synchronized中的Object对象锁作用是一样的,都可以控制当前锁管理的线程。
    2. 优点:
      1. api比Object更多
      2. 可以创建多个Condition控制不同组的线程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值