02.第二阶段、实战Java高并发程序设计模式-4.无锁

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指令线程

cmpxchg
/*
accumulator = AL, AX, or EAX, depending on whether
a byte, word, or doubleword comparison is being performed */
if(accumulator == Destination) {orm

ZF = 1;对象

Destination = Source; }接口

else {
ZF = 0;rem

accumulator = Destination; }get

2. 无锁类的使用io

2.1. AtomicInteger

2.1.1. 概述 Number

2.1.2. 主要接口

public

final

int

get()

 

//取得当前值 //设置当前值

//设置新值,并返回旧值

public

final

void

set(int

newValue)

 

public

final

int

getAndSet(int

newValue)

 

public

final

boolean

compareAndSet(int

expect,

int

u)

//若是当前值为expect,则设置为u

public

final

int

getAndIncrement()

//当前值加1,返回旧值 //当前值减1,返回旧值

//当前值增长delta,返回旧值 //当前值加1,返回新值 //当前值减1,返回新值

//当前值增长delta,返回新值

public

final

int

getAndDecrement()

 

public

final

int

getAndAdd(int

delta)

 

public

final

int

incrementAndGet()

 

public

final

int

decrementAndGet()

 

public

final

int

addAndGet(int

delta)

2.1.3. 主要接口的实现

2.2. Unsafe

2.2.1. 概述

非安全的操做,好比: 根据偏移量设置值 park() 底层的CAS操做

非公开API,在不一样版本的JDK中, 可能有较大差别

2.2.2. 主要接口

//得到给定对象偏移量上的int值
public native int getInt(Object o, long offset); //设置给定对象偏移量上的int值
public native void putInt(Object o, long offset, int x); //得到字段在对象中的偏移量
public native long objectFieldOffset(Field f); //设置给定对象的int值,使用volatile语义
public native void putIntVolatile(Object o, long offset, int x); //得到给定对象对象的int值,使用volatile语义
public native int getIntVolatile(Object o, long offset); //和putIntVolatile()同样,可是它要求被操做字段就是volatile类型的 public native void putOrderedInt(Object o, long offset, int x);

2.3. AtomicReference

2.3.1. 概述

对引用进行修改 是一个模板类,抽象化了数据类型

2.3.2. 主要接口

get()
set(V) compareAndSet() getAndSet(V)

2.4. AtomicStampedReference

2.4.1. 概述

ABA问题

2.4.2. 主要接口

//比较设置 参数依次为:指望值 写入新值 指望时间戳 新时间戳
public boolean compareAndSet(V expectedReference,V newReference,int expectedStamp,int newStamp) //得到当前对象引用
public V getReference()
//得到当前时间戳
public int getStamp()
//设置当前对象引用和时间戳
public void set(V newReference, int newStamp)

2.5. AtomicIntegerArray

2.5.1. 概述

支持无锁的数组

2.5.2. 主要接口

//得到数组第i个下标的元素
public final int get(int i)
//得到数组的长度
public final int length()
//将数组第i个下标设置为newValue,并返回旧的值
public final int getAndSet(int i, int newValue) //进行CAS操做,若是第i个下标的元素等于expect,则设置为update,设置成功返回true public final boolean compareAndSet(int i, int expect, int update)

//将第i个下标的元素加1
public final int getAndIncrement(int i) //将第i个下标的元素减1
public final int getAndDecrement(int i) //将第i个下标的元素增长delta(delta能够是负数) public final int getAndAdd(int i, int delta)

2.6. AtomicIntegerFieldUpdater

2.6.1. 概述

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

2.6.2. 主要接口 AtomicIntegerFieldUpdater.newUpdater()

incrementAndGet()

2.6.3. 小说明

1. Updater只能修改它可见范围内的变量。由于Updater使用反射获得这个变量。若是变量不可见,就会出错。

好比若是score申明为private,就是不可行的。
2. 为了确保变量被正确的读取,它必须是volatile类型的。若是咱们原有代码中未申明这个类型,那么简单得 申明一下就行,这不会引发什么问题。

3. 因为CAS操做会经过对象实例中的偏移量直接进行赋值,所以,它不支持static字段(Unsafe. objectFieldOffset()不支持静态变量)。

3. 无锁算法详解

3.1. 无锁的Vector实现

相关文章
相关标签/搜索