CAS && Unsafe的使用

1 CAS

1.1 基本介绍

Compare And Set,直译过来就是比较并设值,解决多线程并行情况下使用锁造成性能损耗的一种机制,CAS操作包含三个操作数—内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。

/**
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
*
* @param expect the expected value
* @param update the new value
* @return {@code true} if successful. False return indicates that
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(int expect, int update) {
    return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

1.2 案例

public static void main(String[] args)  {
    //期望12,设置为20
    AtomicInteger atomicInteger=new AtomicInteger(10);
    boolean b = atomicInteger.compareAndSet(12, 20);
    System.out.println(b);
    System.out.println(atomicInteger.get());
    System.out.println("#######################");
    //期望10,设置为20
    AtomicInteger atomicInteger1=new AtomicInteger(10);
    boolean b1 = atomicInteger1.compareAndSet(10, 20);
    System.out.println(b1);
    System.out.println(atomicInteger1.get());
}

在这里插入图片描述

2 Unsafe

2.1 简介

Java 不能直接访问操作系统底层,而是通过本地方法来访问。Unsafe 类提供了硬件级别的原子操作。Unsafe 类在 sun.misc 包下,不属于 Java 标准。很多 Java 的基础类库,包括一些被广泛使用的高性能开发库都是基于 Unsafe 类开发,比如 Netty、Hadoop、Kafka 等。
(1) Unsafe 是用于在实质上扩展 Java 语言表达能力、便于在更高层(Java 层)代码里实现原本要在更低层(C 层)实现的核心库功能用的。
(2) 这些功能包括裸内存的申请/释放/访问,低层硬件的 atomic/volatile 支持,创建未初始化对象等。
(3) 它原本的设计就只应该被标准库使用,因此不建议在生产环境中使用。

2.2 获取Unsafe

public final class UnsafeUtils {
    private UnsafeUtils() {
    }
    /**
     * 获取Unsafe
     */
    public static Unsafe getUnsafe() {
        try {
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            return (Unsafe) field.get(null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

3 Unsafe实现CAS锁

3.1 接口

public interface Counter {

    void increment();

    long getCounter();

}

3.2 CasCounter

public class CasCounter implements Counter {

    private volatile long counter = 0;

    private Unsafe unsafe;

    private long offset;

    public CasCounter() throws Exception {
        //获取unsafe
        unsafe = UnsafeUtils.getUnsafe();
        //设置偏移量为counter
        offset = unsafe.objectFieldOffset(CasCounter.class.getDeclaredField("counter"));
    }

    @Override
    public void increment() {
        long current = counter;
        /**
         * compareAndSwapLong(Object var1, long var2, long var4, long var6)
         * var1:对象,var2:偏移量,var4:expect(期望值),var6:update(更新值)
         */
        while (!unsafe.compareAndSwapLong(this, offset, current, current + 1)) {
            current=counter;
        }
    }

    @Override
    public long getCounter() {
        return counter;
    }
}

3.3 测试类

/**
 * @Description: 每个线程对Counter进行累加MAX_SUM次,MAX_THREAD个线程同时累加
 * @Auther: zhurongsheng
 * @Date: 2020/4/2 11:15
 */
public class UnsafeTest {


    private static final int MAX_THREAD = 1000;

    private static final int MAX_SUM = 10000;


    public static void main(String[] args) throws Exception {

        ExecutorService service = Executors.newFixedThreadPool(MAX_THREAD);
        Counter counter = new CasCounter();
        for (int i = 0; i < 1000; i++) {
            service.submit(new CounterRunnable(counter, MAX_SUM));
        }
        //关闭不接受新任务
        service.shutdown();
        //阻塞,直到所有任务执行完毕 或 1小时后中断
        service.awaitTermination(1, TimeUnit.HOURS);
        System.out.println("Counter result:" + counter.getCounter());
    }
}

在这里插入图片描述

4 unsafe创建对象绕过对象的构造

4.1 pojo

class Simple {
    public Simple() {
        System.out.println("Simple invoke NoArgsConstructor");
    }
    public void sayHello(){
        System.out.println("hello world");
    }
}

4.2 测试类

/**
* @Description: 通过Unsafe创建对象可以绕过对象的构造
* @Auther: zhurongsheng
* @Date: 2020/4/2 13:45
*/
public class UnsafeTest {
    public static void main(String[] args) throws Exception {
        //通过new 直接新建Simple
        System.out.println("创建:");
        new Simple();
        //通过反射创建Simple
        System.out.println("反射:");
        Simple.class.newInstance();
        //通过unsafe
        System.out.println("【unsafe】:");
        Unsafe unsafe = UnsafeUtils.getUnsafe();
        Simple instance = (Simple) unsafe.allocateInstance(Simple.class);
        instance.sayHello();
    }
}

在这里插入图片描述

5 unsafe直接修改私有变量

5.1 pojo

class Simple {
    private boolean access = false;
    private boolean allow() {
        return access == true;
    }
    public void work() {
        if (allow()) {
            System.out.println("工作使我快乐");
            return;
        }
        System.out.println("我不要工作,来世我要当一个被子,要么躺床上,要么晒太阳。");
    }
}

5.2 测试类

public class UnsafeTest {
    public static void main(String[] args) throws Exception {
        //1 直接new
        System.out.println("直接创建对象:");
        Simple simple1 = new Simple();
        simple1.work();
        System.out.println("###########################");
        //2 反射
        System.out.println("通过反射直接修改私有变量:");
        Simple simple2 = Simple.class.newInstance();
        Field access = simple2.getClass().getDeclaredField("access");
        access.setAccessible(true);
        access.set(simple2,true);
        simple2.work();
        System.out.println("###########################");
        //3 unsafe
        System.out.println("通过unsafe修改私有变量:");
        Unsafe unsafe = UnsafeUtils.getUnsafe();
        Simple simple3 = Simple.class.newInstance();
        Field access1 = simple3.getClass().getDeclaredField("access");
        //对象,偏移量,设置值
        unsafe.putBoolean(simple3,unsafe.objectFieldOffset(access1),true);
        simple3.work();
    }
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_34125999/article/details/105272882
Cas