8共享模型之工具-8.2JUC

目录

    • 一、AQS原理
      • 1、相关概念
      • 2、实现不可重入锁
      • 3、总结
    • 二、ReentrantLock 原理

一、AQS原理

1、相关概念

AQS全称是 AbstractQueuedSynchronizer,是阻塞式锁和相关的同步器工具的框架
8共享模型之工具-8.2JUC_第1张图片

2、实现不可重入锁

实现不可重入锁需要分两步来走,一是实现自定义同步器,二是实现自定义锁

自定义同步器

class MySync extends AbstractQueuedSynchronizer {

        // 尝试去获取锁
        @Override
        protected boolean tryAcquire(int i) {
            // compareAndSetState(0, 1): 尝试着将state的值从 0改为1
            if (compareAndSetState(0, 1)) {
                // 将持有锁的线程改为当前线程
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        // 尝试去释放锁
        @Override
        protected boolean tryRelease(int i) {
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        // 判断是否持有独占锁
        @Override
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }

        protected Condition newCondition() {
            return new ConditionObject();
        }
    }

自定义锁
有了自定义同步器,很容易复用 AQS ,实现一个功能完备的自定义锁

public class MyLock implements Lock {

    // 自定义同步器 , 实现的是不可重入锁

    private MySync sync = new MySync();

    @Override
    // 尝试,不成功,进入等待队列
    public void lock() {
        sync.acquire(1);
    }

    @Override
    // 尝试,不成功,进入等待队列,可打断
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    @Override
    // 尝试一次,不成功返回,不进入队列
    public boolean tryLock() {
        return sync.tryAcquire(1);
    }

    @Override
    // 尝试,不成功,进入等待队列,有时限
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(time));
    }

    @Override
    // 释放锁
    public void unlock() {
        sync.release(1);
    }

    @Override
    // 生成条件变量
    public Condition newCondition() {
        return sync.newCondition();
    }
}

测试

@Slf4j(topic = "c.MyLockTest")
public class MyLockTest {

    public static void main(String[] args) {
        MyLock lock = new MyLock();
        new Thread(() -> {
            lock.lock();
            try {
                log.debug("locking...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            } finally {
                log.debug("unlocking...");
                lock.unlock();
            }
        },"t1").start();

        new Thread(() -> {
            lock.lock();
            try {
                log.debug("locking...");
            } finally {
                log.debug("unlocking...");
                lock.unlock();
            }
        },"t2").start();
    }
}

可以看到只有当t1线程释放锁之后,t2线程才能获取到锁
8共享模型之工具-8.2JUC_第2张图片

3、总结

AQS 要实现的功能目标:

  • 阻塞版本获取锁 acquire 和非阻塞的版本尝试获取锁 tryAcquire
  • 获取锁超时机制
  • 通过打断取消机制
  • 独占机制及共享机制
  • 条件不满足时的等待机制

二、ReentrantLock 原理

你可能感兴趣的:(Java多线程,java多线程)