对象的属性修改类型、JDK1.8新增类、J.U.C之AQS、AQS资源共享方式、CLH同步队列

对象的属性修改类型
如果需要原子更新某个类里的某个字段时,需要用到对象的属性修改类型原子类。
    AtomicIntegerFieldUpdater:原子更新整形字段的更新器
    AtomicLongFieldUpdater :原子更新长整形字段的更新器
    AtomicReferenceFieldUpdater : 原子更新引用类形字段的更新器
但是他们的使用通常有以下几个限制:
●限制1 :操作的目标不能是statiC类型,前面说到的unsafe提取的是非static类型的属性偏移量,如果是static
类型在获取时如果没有使用对应的方法是会报错的,而这个Updater并没有使用对应的方法。
●限制2 :操作的目标不能是final类型的,因为final根本没法修改。
●限制3 :必须是volatile类型的数据,也就是数据本身是读一 致的。
●限制4:属性必须对当前的Updater所在的区域是可见的,也就是private如果不是当前类肯定是不可见的,protected如果不存在父子关系也是不可见的, default如果不是在同一个package 下也是不可见的。
实现方式:通过反射找到属性,对属性进行操作。

JDK1.8新增类

    LongAdder :长整型原子类
    DoubleAdder :双浮点型原子类
    LongAccumulator :类似LongAdder ,但要更加灵活(要传入一个函数式接口)
    DoubleAccumulator :类似DoubleAdder ,但要更加灵活(要传入一个函数式接口)

LongAdder是jdk1 .8提供的累加器,基于Striped64实现,所提供的API基本上可以替换原先的AtomicLong。

LongAdder类似于AtomicLong是原子性递增或者递减类. AtomicLong已经通过CAS提供了非阻塞的原子性操作,相比使用阻塞算法的同步器来说性能已经很好了,但是JDK开发组并不满足,因为在非常高的并发请求下AtomicLong的性能不能让他们接受,虽然AtomicLong使用CAS但是CAS失败后还是通过无限循环的自旋锁不断尝试。


J.U.C之AQS
AQS简介
AQS(AbstractQueuedSynchronizer ) , 即队列同步器。它是构建锁或者其他同步组件的基础框架(如
ReentrantLock. ReentrantReadWriteLock. Semaphore等 ) , JUC并发包的作者( Doug Lea )期望它能够成为实现大部分同步需求的基础。它是UC并发包中的核心基础组件。
在这里我们只是对AQS进行了解.它只是一个抽象类,但是JUC中的很多组件都是基于这个抽象类,也可以说这个AQS是多数JUC组件的基础。

AQS的作用

Java的内 锁- -直都是备受争议的,在JDK 1.6之前, synchroni2ed这个重星级锁其性能- -直都是较为低下 ,虽然在1.6后,进行大量的锁优化策略,但是与Lock相比synchronized还是存在一些缺陷的: 它缺少了获取锁与释放锁的可操作性,可中断、超时获取锁,而且独占式在高并发场景下性能大打折扣。

AQS解决了实现同步器时涉及到的大量细节问题,例如获取同步状态、FIFO同步队列。 基于AQS来构建同步器可以带来很多好处。它不仅能够极大地减少实现工作,而且也不必处理在多个位置上发生的竞争问题。

state状态
AQS维护了一个volatile int类型的变量state表示当前同步状态。当state>0时表示已经获取了锁,当state = 0时表示释放了锁

它提供了三个方法来对同步状态state进行操作:
    getState() :返回同步状态的当前值
    setState():设置当前同步状态
    compareAndSetState( :使用CAS设置当前状态,该方法能够保证状态设置的原子性
这三种操作均是CAS原子操作,其中compareAndSetState的实现依赖于Unsafe的compareAndSwapInt()方法

资源共享方式
AQS定义两种资源共享方式:
●Exclusive (独占,只有一个线程能执行,如ReentrantLock) L
●Share(共享,多个线程可同时执行,如Semaphore/CountDownLatch )


不同的自定义同步器争用共享资源的方式也不同。自定义同步器在实现时只需要实现共享资源state的获取与释放方式即可,至于具体线程等待队列的维护(如获取资源失败入队/唤醒出队等) , AQS已经在顶层实现好了。自定义同步器实现时主要实现以下几种方法:
●isHeldExclusively() :当前同步器是否在独占式模式下被线程占用,一般该方法表示是否被 当前线程所独
占。只有用到condition才需要去实现它。
●tryAcquire(int) :独占方式。尝试获取同步状态,成功则返回true ,失败则返回false.其他线程需要等待该线程释放同步状态才能获取同步状态。
●tryRelease(int): 独占方式。尝试释放同步状态,成功则返回true ,失败则返回false.
●tryAcquireShared(int):共享方式。尝试获取同步状态。负数表示失败; 0表示成功,但没有剩余可用资
源;正数表示成功.且有剩余资源。
●tryReleaseShared(int):共享方式。尝试释放同步状态.如果释放后允许唤醒后续等待结点,返回true,
否则返回false.

CLH同步队列
AQS内部维护着一个FIFO队列 ,该队列就是CLH同步队列,遵循FIFO原则( First Input First Output先进先出)。CLH同步队列是一个FIFO双向队列, AQS依赖它来完成同步状态的管理。

当前线程如果获取同步状态失败时,AQS则会将当前线程已经等待状态等信息构造成一个节点( Node )并将其入到CLH同步队列,同时会阻塞当前线程,当同步状态释放时,会把首节点唤醒(公平锁) , 使其再次尝试获取同步状态。


入列
CLH队列入列非常简单,就是tal指向新节点新节点的prev指向当前最后的节点,当前最后一个节点的next
指向当前节点。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值