avatar

java并发

juc

CAS

描述CAS是通过指令集完成的操作,一共为三个值,L表示内存中的值,E表示期待比较的值,VL=E时将V替换内存值

  • Atomic类
AtomicInteger
1
2
3
4
5
6
7
8
9
10
11
12
13
//valueOffset表示atomicInteger中value属性的偏移量
ublic final int getAndSet(int newValue) {
return unsafe.getAndSetInt(this, valueOffset, newValue);
}
//=================unsafe实现====================
public final int getAndSetInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);//获取当前内存值
} while(!this.compareAndSwapInt(var1, var2, var5, var4));//CAS操作

return var5;
}
  • AtomicMarkableReference
    ABA问题:表示线程1修改变量A时,cas操作过程中,若线程2导致A->B->A,而线程1的判断发生在线程2的最后一部,那么就是ABA问题了
AtomicMarkableReference
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
private static class Pair<T> {
final T reference;
final boolean mark;
private Pair(T reference, boolean mark) {
this.reference = reference;
this.mark = mark;
}
static <T> Pair<T> of(T reference, boolean mark) {
return new Pair<T>(reference, mark);
}
}

private volatile Pair<V> pair; //vlolatile禁止重排,线程可见

public boolean compareAndSet(V expectedReference,
V newReference,
boolean expectedMark,
boolean newMark) {
Pair<V> current = pair;
return
expectedReference == current.reference &&
expectedMark == current.mark &&
((newReference == current.reference &&
newMark == current.mark) ||
casPair(current, Pair.of(newReference, newMark)));
}

private boolean casPair(Pair<V> cmp, Pair<V> val) {
return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
}
  • 说明
    • 线程1执行到return语句,线程2发生了A->B->A,如果这个A.mark,A.ref不变,那么不会执行cas
      ,如果变了,那么就应该执行cas,这样就避免的aba问题.
    • 如果线程1执行到了||后边即cas语句,线程2发生了A-B->A,此时这个A不可能是线程A中的current,
      因为Pair.of是new出来的,这也就避免aba问题.
    • 总而言之,使用cas就是就是为了提高性能,而不是直接使用悲观锁
文章作者: fancylight
文章链接: https://www.fancylight.top/2020/03/31/java%E5%B9%B6%E5%8F%91/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 博客
打赏
  • 微信
    微信
  • 支付寶
    支付寶

评论