AQS之ReentrantLock独占锁源码解析

 一、基础概念

AQS(AbstractQueuedSynchronizer):是jdk并发包java.util.concurrent下绝大部分工具类实现的基础。

管程:是指管理共享变量以及对共享变量操作的过程,让它们支持并发

JVM层对管程的实现:synchronized

JAVA层对管程的实现:AQS抽象层,对AQS进行实现

JAVA的线程安全问题解决方案:cas+自旋(会出现空转cpu的问题)、synchronized、reentrantLock 会阻塞未获取锁的线程

----- JDK中提供的大多数的同步器如Lock,Latch,Barrier等,都是基于AQS框架来实现的,一般事通过一个内部类Sync继承AQS将同步器所有调用都映射到Sync对应的方法        

AQS之ReentrantLock独占锁源码解析_第1张图片

  二、AQS

特性:阻塞等待队列    共享/独占   公平/非公平  可重入  允许中断

 AQS内部维护属性 volatile int state

        表示同步的状态,对于独占锁而言,这个属性可以网上增加,每重入一次就+1;对于共享锁而言,就是资源个数,每来一个-1,当减为0以后,后续的资源就不能获取到锁了。

AQS之ReentrantLock独占锁源码解析_第2张图片

         state三种访问方式

        getState()  setState()  compareAndSetState()

AQS定义两种资源共享方式:

Exclusive 独占,只有一个线程能获取锁执行,如ReentrantLock

Share  共享 ,多个线程可以同时执行,如 Semaphore/CountDownLatch

AQS定义两种等待队列:

同步等待队列:主要用于维护获取锁失败时入队的线程

条件等待队列:调用await()的时候会释放锁,然后线程会加入到条件队列,调用signal()唤醒的时候会把条件队列中的线程节点移动到同步队列中,等待再次获得锁。

        不同的自定义同步器竞争共享资源的方式也不同。自定义同步器在实现时只需要实现共享 资源state的获取与释放方式即可,至于具体线程等待队列的维护(如获取资源失败入队/唤醒出队等),AQS已经在顶层实现好了。自定义同步器实现时主要实现以下几种方法:

  1. isHeldExclusively():该线程是否正在独占资源。只有用到condition才需要去实现它

tryAcquire(int):独占方式。尝试获取资源,成功则返回true,失败则返回false。

tryRelease(int):独占方式。尝试释放资源,成功则返回true,失败则返回false。

tryAcquireShared(int):共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。

tryReleaseShared(int):共享方式。尝试释放资源,如果释放后允许唤醒后续等待结点返回true,否则返回false。

AQS之ReentrantLock独占锁源码解析_第3张图片

 同步等待队列 (双向链表结构)

        基于双向链表数据结构的队列是FIFO先进先出线程等待队列

AQS之ReentrantLock独占锁源码解析_第4张图片

 条件等待队列

        AQS中条件队列是使用单向列表保存的,用nextWaiter来连接: 调用await方法阻塞线程;

当前线程存在于同步队列的头结点,调用await方法进行阻塞(从同步队列转化到条 件队列

自定义实现AQS:

实现加锁 解锁逻辑

public class MyselfLock extends AbstractQueuedSynchronizer {

    @Override
    protected boolean tryAcquire(int unused) {
        //cas 实现加锁逻辑 默认 state =0 ,
        if(compareAndSetState(0,1)){
            //将当前的线程进行绑定,设置为一个独占的线程
            setExclusiveOwnerThread(Thread.currentThread());
            return true;
        }
        return false;
    }

    @Override
    protected boolean tryRelease(int unused) {
        //释放锁
        setExclusiveOwnerThread(null);
        setState(0);
        return true;
    }
    public void lock(){
        acquire(1);
    }
    public boolean tryLock(){
        return tryAcquire(1);
    }
    public void unlock(){
        release(1);
    }

AQS独占锁的加锁解锁图

AQS之ReentrantLock独占锁源码解析_第5张图片

 

你可能感兴趣的:(java)