zoukankan      html  css  js  c++  java
  • CAS中,如何避免比较和修改之间插入线程?

    这说的并不是ABA问题,ABA问题是比较之前某个值被改变成另一个相同的值的问题

    先来回顾原语:原子性的语句,就是一堆机器指令,CPU要么全部执行,要么全部不执行

    JAVA中的CAS:

    public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5)

    查看其native源码:

    UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h))
      UnsafeWrapper("Unsafe_CompareAndSwapObject");
      oop x = JNIHandles::resolve(x_h); // 新值
      oop e = JNIHandles::resolve(e_h); // 预期值
      oop p = JNIHandles::resolve(obj);
      HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset);// 在内存中的具体位置
      oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e, true);// 调用了另一个方法
      jboolean success  = (res == e);  // 如果返回的res等于e,则判定满足compare条件(说明res应该为内存中的当前值),但实际上会有ABA的问题
      if (success) // success为true时,说明此时已经交换成功(调用的是最底层的cmpxchg指令)
        update_barrier_set((void*)addr, x); // 每次Reference类型数据写操作时,都会产生一个Write Barrier暂时中断操作,配合垃圾收集器
      return success;
    UNSAFE_END
    

    可以看到源码中又调用了另一个原子性的方法:oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e, true);保证其原子性,避免被其它线程插入;到最后会转换成完成CAS功能的原语

    参考:

    JUC系列第三篇-CAS算法详解

  • 相关阅读:
    sessionid如何产生?由谁产生?保存在哪里?
    springmvc原理
    java基础面试题
    mysql数据库去重复
    git安装和初次使用
    String的按值传递,java传参都是传值
    sublime Text3使用笔记
    git命令使用记录
    Git:错误:error:src refspec master does not match any
    java并发编程实战学习(3)--基础构建模块
  • 原文地址:https://www.cnblogs.com/linyh99/p/14670521.html
Copyright © 2011-2022 走看看