`

无锁(CAS)编程

 
阅读更多

 1.  无 锁类 的原理 详 解

1.1.CAS

       CAS算法的过程是这样:它包含3个参数CAS(V,E,N)。V表示要更新的变量,E表示预期值,N表示新值。仅当V值等于E值时,才会将V的值设为N,如果V值和E值不同,则说明已经有其他线程做了更新,则当前线程什么都不做。最后,CAS返回当前V的真实值。CAS操作是抱着乐观的态度进行的,它总是认为自己可以成功完成操作。当多个线程同时使用CAS操作一个变量时,只有一个会胜出,并成功更新,其余均会失败。失败的线程不会被挂起,仅是被告知失败,并且允许再次尝试,当然也允许失败的线程放弃操作。基于这样的原理,CAS操作即时没有锁,也可以发现其他线程对当前线程的干扰,并进行恰当的处理。

1.2.CPU 指令

    CAS操作是在一条cpu指令中完成。具有原子性,线程安全

cmpxchg
/*
accumulator = AL, AX, or EAX, depending on whether
a byte, word, or doubleword comparison is being performed
*/
if(accumulator == Destination) {
ZF = 1;
Destination = Source;
}
else {
ZF = 0;
accumulator = Destination;
}

 

2.  无 锁类 

2.1AtomicInteger

AtomicInteger和Integer一样,都继承与Number类

public class AtomicInteger extends Number implements java.io.Serializable

 AtomicInteger里面有很多CAS操作,典型的有:

public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

 这里来解释一下unsafe.compareAndSwapInt方法,他的意思是,对于this这个类上的偏移量为valueOffset的变量值如果与期望值expect相同,那么把这个变量的值设为update。

其实偏移量为valueOffset的变量就是value

static {
      try {
        valueOffset = unsafe.objectFieldOffset
            (AtomicInteger.class.getDeclaredField("value"));
      } catch (Exception ex) { throw new Error(ex); }
}

 

我们此前说过,CAS是有可能会失败的,但是失败的代价是很小的,所以一般的实现都是在一个无限循环体内,直到成功为止。

public final int getAndIncrement() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))
                return current;
        }
    }

Unsafe类中使用

从类名就可知,Unsafe操作是非安全的操作,比如:

  • 根据偏移量设置值(在刚刚介绍的AtomicInteger中已经看到了这个功能
  • park()(把这个线程停下来,在以后的Blog中会提到)
  • 底层的CAS操作

非公开API,在不同版本的JDK中,可能有较大差异

 

2.2 AtomicReference(模板类)、AtomicStampedReference、AtomicIntegerArray(无锁数组)不一一列举

2.3 AtomicIntegerFieldUpdater(普通变量也享受原子)

2.3.1. 概述

让普通变量也享受原子操作

2.3.2. 主要接口

AtomicIntegerFieldUpdater.newUpdater()

incrementAndGet()

2.3.3. 小 说 明

1.Updater只能修改它可见范围内的变量。因为Updater使用反射得到这个变量。如果变量不可见,就会出错。

比如如果score申明为private,就是不可行的。

2.为了确保变量被正确的读取,它必须是volatile类型的。如果我们原有代码中未申明这个类型,那么简单得

申明一下就行,这不会引起什么问题。

3.  由于CAS操作会通过对象实例中的偏移量直接进行赋值,因此,它不支持static字段(Unsafe.

objectFieldOffset()不支持静态变量)。

 

分享到:
评论

相关推荐

    Java语言中cas指令的无锁编程实现实例

    主要介绍了Java语言中cas指令的无锁编程实现实例,具有一定参考价值,需要的朋友可以了解下。

    一个无锁算法的库实现

    一个无锁算法的库实现, 采用cas实现.

    Java并发的基础知识.docx

    通常减少上下文切换可以采用无锁并发编程,CAS算法,使用最少的线程和使用协程。 比如:悲观锁就会导致频繁的上下文切换,而频繁的上下文切换可能无法发挥出多线程编程的优势 无锁并发编程 可以参照jdk1.7分段锁的...

    锁与原子操作CAS以及无锁队列的底层实现相关资源

    锁与原子操作CAS以及无锁队列的底层实现相关资源

    汪文君高并发编程实战视频资源下载.txt

     高并发编程第三阶段04讲 利用CAS构造一个TryLock自定义显式锁-增强并发情况下.mp4  高并发编程第三阶段05讲 AtomicBoolean源码分析.mp4  高并发编程第三阶段06讲 AtomicLong源码分析.mp4  高并发编程第三阶段07...

    玩转多线程编程

    无锁编程(Lock Free) 阻塞型同步(Blocking Synchronization) 非阻塞型同步(Non-blocking Synchronization) 优先级反转(Priority Inversion) 优先级继承(Priority Inheritance) 优先级顶置(Priority ...

    汪文君高并发编程实战视频资源全集

     高并发编程第三阶段04讲 利用CAS构造一个TryLock自定义显式锁-增强并发情况下.mp4  高并发编程第三阶段05讲 AtomicBoolean源码分析.mp4  高并发编程第三阶段06讲 AtomicLong源码分析.mp4  高并发编程第三阶段07...

    一天搞定Java并发编程

    无锁并发编程:多线程竞争锁时,会引起上下文切换,所以多线程处理数据时,可以用一些办法来避免使用锁,如将数据的ID按照Hash算法取模分段,不同的线程处理不同段的数据 CAS算法:Java的Atomic包使用的CAS算法来...

    rs-lockfree:实用的危险指标工具,提供无锁防锈工具

    显然,原子操作(如CAS)在无锁编程中至关重要。 参考计数有2个缺陷: 每个读数都需要修改全局参考计数。 在高并发情况下对同一对象进行原子操作可能会成为性能瓶颈。 管理参考对象将带来额外的维护成本,并增加...

    FastFlow: programming multi-core-开源

    FastFlow是一个C / C ++编程框架,支持在多核/多核GPU和分布式平台上开发基于模式的并行程序。 FastFlow运行时基于非阻塞线程和无锁队列。 由于其非常有效的无CAS通信/同步支持(例如,很少的时钟周期内核间延迟),...

Global site tag (gtag.js) - Google Analytics