CAS方法的使用




最近忙着復習,筆記倒是寫了很多但沒有整理出來,后期抽時間統一上傳


1. CAS

在並發編程下能經常看到CAS,全名Compare and Swap(比較和交換)。是JDK提供的非阻塞原子性操作,它通過硬件保證了比較-交換這個操作的原子性,主要是處理器級別提供了原子性操作。和重量級鎖(Synchronized)對比,免去了線程上下文切換的開銷,是個不錯的輕量級鎖


實現原理:該方法有四個參數,分別是對象內存位置,對象中變量的偏移量,變量預期值,變量更新值。如果對象obj內存偏移量為offset的變量的值為expect,則使用update替換舊的值expect




2. Unsafe

JDK的Unsafe類提供了一系列的compareAndSwap*方法,下面列出這次用到的方法

  • long objectFieldOffet(Field file) 獲取字段的偏移量
  • boolean compareAndSwaoInt(Object obj,long offset,int expect,int update) CAS方法

因為Unsafe是個直接操作內存的不安全類,所以JDK規定只有BootStrap類加載器加載的類才能使用Unsafe類,比如rt.jar包下的類就可以。那么我們自定義的使用Application加載器加載的類怎么使用Unsafe呢?答案是:萬能的反射,方法如下


import sun.misc.Unsafe;
import java.lang.reflect.Field;

public class UnsafeUtil {

    public static Unsafe getInstance() throws NoSuchFieldException, IllegalAccessException {
        
        // 獲取字段
        Field filed = Unsafe.class.getDeclaredField("theUnsafe");
        
        // 設置可訪問
        filed.setAccessible(true);
        
        // 返回Unsafe實例
        return (Unsafe)filed.get(null);
    }
}

注意:使用IDEA方便,而eclipse不能直接導入import sun.misc.Unsafe,需要自行解決


import sun.misc.Unsafe;
import java.lang.reflect.Field;

public class Test {

	// 需要CAS修改的字段
    private int i = 0;

    public int getI() {
        return i;
    }

    public void setI(int i) {
        this.i = i;
    }


    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {

        // 獲取Unsafe實例
        Unsafe  unsafe = UnsafeUtil.getInstance();

        // 獲取字段 i 的偏移量
        Test test = new Test();
        Field field = test.getClass().getDeclaredField("i");
        long offset = unsafe.objectFieldOffset(field);

        // CAS修改,返回布爾值
        boolean isSuccess = unsafe.compareAndSwapInt(test,offset,0,1);

        // 打印
        System.out.println(isSuccess);
        System.out.println(test.getI());

    }
}

打印

true
1


《Java並發編程之美》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM