【java】 如何自己写一把多线程锁 上 创建 Unsafe类对象

1.先看lock接口

看下这个接口有几个方法等着我们重写

【java】 如何自己写一把多线程锁 上 创建 Unsafe类对象_第1张图片

六个方法 加锁,尝试加锁,定时尝试加锁,解锁 主要是这是个方法 其他两个骚方法放一边 不玩这么骚的

【java】 如何自己写一把多线程锁 上 创建 Unsafe类对象_第2张图片

2. 准备工作

创建一个类 我这里取名叫 MyReentrantLock 我的可重入锁 实现 lock接口

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * @author sz
 * @DATE 2022/3/16  20:30
 */
public class MyReentrantLock implements Lock {
    @Override
    public void lock() {

    }

    @Override
    public void unlock() {

    }

    @Override
    public boolean tryLock() {
        return false;
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return false;
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {

    }

    @Override
    public Condition newCondition() {
        return null;
    }
}

3.模仿

我们先来看下JUC包的下锁都是怎么实现的

调用 ReentrantLock().lock()方法 发现走的是 sync.lock() sync是什么呢 ? 点一下

image-20220316210013061

哦 原来是继承了 AbstractQueuedSynchronizer 的一个 静态抽象内部类

AbstractQueuedSynchronizer 又是什么 点进去再看一下

算了 2000多行代码 简单说一下吧 AbstractQueuedSynchronizer 简称 AQS 也就是大名鼎鼎的 抽象队列同步器

没听过 ? 不知道抽象队列同步器? 简单说下就是一个框架 用来做同步器也就是锁的框架 具体的百度一下

从上面那个动图也可以看到 最后走到了 AbstractQueuedSynchronizer 里面 调用 unsafe的 compareAndSwapInt () 方法 也就是乐观锁的实现

unsafe类又是啥 看名字 不安全的类 操作底层的 调用compareAndSwapInt 方法 要传四个参数

image-20220316211058831

第一个参数时你要操作的对象 第二个参数是属性的偏移量 第三个是期望值 第四个是要修改的值

怎么获取 属性的偏移量呢 ? 看看源码是怎么写的

stateOffset = unsafe.objectFieldOffset
                (AbstractQueuedSynchronizer.class.getDeclaredField("state"));

哦 原来是调用 unsafe.objectFieldOffset()

我们也来试试获取一下偏移量

先尝试创建 unsafe 对象

new unsafe 咦 不对劲,不能new 看下构造方法 ,好家伙 私有的 在看看有没有静态方法能返回unsafe对象

找到了

Unsafe.getUnsafe()

返回一个 unsafe对象 打印输出一下

咦,报错了 什么意思

Exception in thread "main" java.lang.SecurityException: Unsafe

权限异常 不安全?

在看看这个 getUnsafe 方法

【java】 如何自己写一把多线程锁 上 创建 Unsafe类对象_第3张图片

什么意思 获取类加载判断是不是 isSystemDomainLoader

点进去看一下

【java】 如何自己写一把多线程锁 上 创建 Unsafe类对象_第4张图片

null ? null 是什么

JVM将类加载进内存有三个内加载器 不熟悉的可以去看看我之前的帖子 JAVA虚拟机上篇 之 JVM的组成和类的加载过程 一次给你搞明白_秋日的晚霞的博客-CSDN博客

其中最顶层的 BootStrapClassLoader 类加载器就是 null 也就说这个类 只能由 JVM创建 我们不能创建对象 那怎么办

冥思苦想 … 嗯 试试反射

  public static Unsafe getUnsafe() throws Exception {
        //利用反射
        Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
        theUnsafe.setAccessible(true); // 设置为可见
        Unsafe unsafe = (Unsafe) theUnsafe.get(null); // 获取Unsafe对象
        return unsafe;
    }

惊喜的发现创建成功了 到此 自己创建锁的第一步已经实现了

你可能感兴趣的:(多线程,java,android,开发语言)