heima并发14---unsafe--184-187

cas还有park和unpark都是调用的unsafe的方法。

unsafe不能直接调用要通过反射来获得的。

可以看到是私有的单例的,要通过反射来获取的。私有的没有构造方法就只能通过反射获取。

代码:

完整代码:

package cn.itcast.test;

import lombok.Data;
import sun.misc.Unsafe;

import java.lang.reflect.Field;

public class TestUnsafe {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");// 这个是获取的私有的
        theUnsafe.setAccessible(true);// 私有的会设置
        Unsafe unsafe = (Unsafe) theUnsafe.get(null);
        System.out.println(unsafe);
        // 1. 获取域的偏移地址
        long idOffset = unsafe.objectFieldOffset(Teacher.class.getDeclaredField("id"));
        long nameOffset = unsafe.objectFieldOffset(Teacher.class.getDeclaredField("name"));
        Teacher t = new Teacher();
        // 2. 执行 cas 操作
        unsafe.compareAndSwapInt(t, idOffset, 0, 1);
        unsafe.compareAndSwapObject(t, nameOffset, null, "张三");
        // 3. 验证
        System.out.println(t);
    }
}
@Data
class Teacher {
    volatile int id;
    volatile String name;
}

公共的可以用getField获取。

私有的用getDeclaredField获取。

静态的不传递对象传递null。

------------------184------------------------

用unsafe去线程安全的修改成员变量。

底层是通过属性的内存的偏移量来定位的。

id和name相对于Teacher的偏移量。

完整的代码:

package cn.itcast.test;
import lombok.Data;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
public class TestUnsafe {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");// 这个是获取的私有的
        theUnsafe.setAccessible(true);// 私有的会设置
        Unsafe unsafe = (Unsafe) theUnsafe.get(null);
        System.out.println(unsafe);
        // 1. 获取域的偏移地址
        long idOffset = unsafe.objectFieldOffset(Teacher.class.getDeclaredField("id"));
        long nameOffset = unsafe.objectFieldOffset(Teacher.class.getDeclaredField("name"));
        Teacher t = new Teacher();
        // 2. 执行 cas 操作
        unsafe.compareAndSwapInt(t, idOffset, 0, 1);
        unsafe.compareAndSwapObject(t, nameOffset, null, "张三");
        // 3. 验证
        System.out.println(t);
    }
}
@Data
class Teacher {
    volatile int id;
    volatile String name;
}

这个代码在赋值的过程中要是有其他的线程干扰就失败了,需要while重试,实现线程安全。

unsafe是通过内存的偏移量去定位属性的。

--------------------185------------------------

我们自己实现cas:

package cn.itcast.test;
import cn.itcast.n4.UnsafeAccessor;
import lombok.extern.slf4j.Slf4j;
import sun.misc.Unsafe;
@Slf4j(topic = "c.Test42")
public class Test42 {
    public static void main(String[] args) {
        Account.demo(new MyAtomicInteger(10000));
    }
}
class MyAtomicInteger implements Account {
    private volatile int value;//要保护的对象
    private static final long valueOffset;
    private static final Unsafe UNSAFE;
    static {
        UNSAFE = UnsafeAccessor.getUnsafe();
        try {
            // 获得偏移量给cas调用
            valueOffset = UNSAFE.objectFieldOffset(MyAtomicInteger.class.getDeclaredField("value"));
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    public int getValue() {
        return value;
    }
    public void decrement(int amount) {
        while(true) {
            int prev = this.value;
            int next = prev - amount;
            if (UNSAFE.compareAndSwapInt(this, valueOffset, prev, next)) {
                break;
            }
        }
    }
    public MyAtomicInteger(int value) {
        this.value = value;
    }
    @Override
    public Integer getBalance() {
        return getValue();
    }
    @Override
    public void withdraw(Integer amount) {
        decrement(amount);
    }
}

------------------186------------------------

小结:

伪共享:加注解,不同的cell对象存在不同得缓存行里面得。

------------------187------------------------

反射:https://blog.csdn.net/h2604396739/article/details/83109292

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值