博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
CAS、AQS、锁以及并发工具
阅读量:5170 次
发布时间:2019-06-13

本文共 2637 字,大约阅读时间需要 8 分钟。

1. CAS原理

中文名叫比较交换---Compare And Swap

CAS(V,E,N)

V表示要更新的值;

E表示预期值;

N表示新值。

比较原则:当V和E相等时,才把N赋值给V;如果V和E不相等时,放弃当前修改。

1.1 如何保证原子性

基于硬件的汇编指令实现原子性,使用CPU指令保证原子性;

// Unsafe 后门类,用于直接操作内存中的数据private static final Unsafe unsafe = Unsafe.getUnsafe();private static final long valueOffset;static {    try {        valueOffset = unsafe.objectFieldOffset            (AtomicInteger.class.getDeclaredField("value"));    } catch (Exception ex) { throw new Error(ex); }}private volatile int value;/** * CAS实现 */public final boolean compareAndSet(int expect, int update) {    return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}/** * 使用自旋的方式保证线程安全 */public final int getAndUpdate(IntUnaryOperator updateFunction) {    int prev, next;    do {        prev = get();        next = updateFunction.applyAsInt(prev);    } while (!compareAndSet(prev, next));    return prev;}

1.2 CAS的缺点

  • 循环时间太长

    有些类限制了自旋的次数

  • 只能保证一个共享变量的原子操作

  • ABA问题

    如果一个值原来是A,变成了B,然后又变成了A,那么在CAS检查的时候会发现没有改变,但是实质上它已经发生了改变,这就是所谓的ABA问题。

    使用类AtomicStampedReference来解决ABA问题。

    如果当前引用 == 预期值,并且当前标志值 == 预期标志值,则就将当前引用和当前标志值赋值为更新值。

/**     * CAS实现     *     * @param expectedReference     引用的预期值     * @param newReference          引用的新值     * @param expectedStamp         标志的预期值     * @param newStamp              标志的新值     */    public boolean compareAndSet(V   expectedReference,                                 V   newReference,                                 int expectedStamp,                                 int newStamp) {        Pair
current = pair; return expectedReference == current.reference && expectedStamp == current.stamp && ((newReference == current.reference && newStamp == current.stamp) || casPair(current, Pair.of(newReference, newStamp))); }

2. AQS原理

AQS----AbstractQueuedSynchronizer的缩写

子类定义为非公共内部帮助器类(私有的内部类继承AQS);写锁的时候的一个帮助器,提供获取锁和是释放锁的功能模板。

acquire(int arg) 以独占模式获取对象,忽略中断。

acquireShared(int arg) 以共享模式获取对象,忽略中断。

tryAcquire(arg) 试图在独占模式下获取对象状态。

tryAcquireShared(int arg) 试图在共享模式下获取对象状态

release(int arg) 以独占模式释放对象。

releaseShared(int arg) 以共享模式释放对象

3. 自定义锁

4. 并发工具类

4.1 CountDownLatch(查询航班)

/** *  新建一个latch为3的锁计数器 */CountDownLatch latch = new CountDownLatch(3);/** * 减少计数,直到计数为0,则释放所有线程 */latch.countDown();/** * 导致当前线程等待,直到计数器为0时。 */latch.await();

4.2 CyclieBarries

CyclicBarrier barrier=new CyclicBarrier(8);/** * 在所有参与者都调用 `await` 方法之前,所有线程一直等待。 */barrier.await();

4.3 Semaphore

是一个计数信号量。

/** * 创建Semaphore */Semaphore sp=new Semaphore(5);/** * 从信号量获取一个许可,如果许可不够,会一直将线程阻塞,否则中断线程。 */sp.acquire();/** * 释放一个许可,将其返回给信号量。 */sp.release();

转载于:https://www.cnblogs.com/zhangqirong/p/11489398.html

你可能感兴趣的文章
Android软件架构及子系统介绍
查看>>
Java命名规范
查看>>
小学生算术
查看>>
BZOJ2823: [AHOI2012]信号塔
查看>>
mysql查询前几条记录
查看>>
java二分法查找实现代码
查看>>
体系编程、SOC编程那些事儿
查看>>
mysql索引的艺术
查看>>
IBM RSA 的语言设置
查看>>
《http权威指南》阅读笔记(二)
查看>>
faster r-cnn cudnn版本不兼容问题
查看>>
[置顶] ListBox控件的数据绑定
查看>>
链表插入排序
查看>>
http://blog.csdn.net/yunye114105/article/details/7997041
查看>>
设计模式这个东西 刚刚发现几种模式好像大同小异啊
查看>>
关于 主键和外键
查看>>
python集合的交,差,并,补集合运算汇总
查看>>
校园分期支付的机遇和风险
查看>>
怕忘记-windows 2003服务器安装Node.js NPM
查看>>
一鍵分享(優化后)
查看>>