【juc】AQS原理

一、概述

  • 1.是一个抽象父类,全称是AbstractQueuedSynchronizer,是阻塞式锁和相关的同步器工具的框架
  • 2.用法是同步器类继承该父类,去实现父类的方法,调用同步器类的方法达到加锁、解锁等目的

二、特点

  • 1.用state属性来表示资源的状态(分为独占模式和共享模式),子类需要定义如何维护这个状态,控制如何获取锁和释放锁
  • 2.getState用来获取state状态
  • 3.setState用来设置state状态
  • 4.compareAndSetState利用cas乐观锁机制设置state状态
  • 5.独占模式是只有一个线程能够访问资源,而共享模式可以允许多个线程访问资源
  • 6.提供了基于FIFO(先进先出)的等待队列,类似于Monitor的EntryList
  • 7.用条件变量来实现等待、唤醒机制,支持多个条件变量,类似于Monitor的WaitSet
  • 8.子类主要实现的方法有tryAcquire、tryRelease、tryAcquireShared、tryReleaseShared、isHeldExclusively,默认会抛出UnsupportedOperationException
  • 9.获取锁
// 如果获取锁失败
if(!tryAcquire(arg){
	// 入队列,可以选择阻塞当前线程,用的是park和unpark机制
}
  • 10.释放锁
// 如果释放锁成功
if(tryRelease(arg)){
	// 让阻塞线程恢复运行
}

三、实现不可重入锁

package com.learning.aqs;

import lombok.extern.slf4j.Slf4j;

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

/**
 * 自定义不可重入锁
 */
@Slf4j
public class NotReentrantLock implements Lock {
    /**
     * 同步器类
     * 独占锁实现
     */
    class Sync extends AbstractQueuedSynchronizer{
        /**
         * 尝试获取锁
         * @param arg 用于可重入锁的计数操作
         * @return
         */
        @Override
        protected boolean tryAcquire(int arg) {
            // 避免其它线程也调用该方法,只能有一个线程加锁成功
            if(compareAndSetState(0, 1)){
                // 加上锁,并设置owner为当前线程
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        /**
         * 尝试释放锁
         * @param arg
         * @return
         */
        @Override
        protected boolean tryRelease(int arg) {
            // 将owner线程置为空,state状态设置为0,即为解锁
            setExclusiveOwnerThread(null);
            // volatile int state; state是volatile修饰的,改值后会加入写屏障,写屏障之前的改动都会同步到主内存中,因此setExclusiveOwnerThread要放在上面
            setState(0);
            return true;
        }

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

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

    private Sync sync = new Sync();

    /**
     * 加锁(不成功则进入等待队列中等待)
     */
    @Override
    public void lock() {
        // 当前线程尝试加锁,如果尝试加锁不成功,将当前线程放入等待队列,tryAcquire只会尝试一次
        sync.acquire(1);
    }

    /**
     * 可打断加锁
     * @throws InterruptedException
     */
    @Override
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    /**
     * 尝试加锁,尝试1次
     * @return
     */
    @Override
    public boolean tryLock() {
        return sync.tryAcquire(1);
    }

    /**
     * 尝试加锁,带超时时间
     * @param time
     * @param unit
     * @return
     * @throws InterruptedException
     */
    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(time));
    }

    /**
     * 解锁
     */
    @Override
    public void unlock() {
        // tryRelease会将状态置为0,将owner线程置为null,不会唤醒等待队列中的阻塞线程
        // release会调用tryRelease方法,改状态为0,将owner线程置为null,唤醒等待队列中的头个线程
        sync.release(1);
    }

    /**
     * 创建条件变量
     * @return
     */
    @Override
    public Condition newCondition() {
        return sync.newCondition();
    }


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

猜你喜欢

转载自blog.csdn.net/qq_32088869/article/details/131902234