【1】请问什么是 AQS?

简介: 【1】请问什么是 AQS?

一、基本概念

  • 全称是 AbstractQueuedSynchronizer
  • 是阻塞式锁和相关的同步器工具的框架

特点:

  • 用 state 属性来表示资源的状态(分独占模式和共享模式),子类需要定义如何维护这个状态,控制如何获取锁和释放锁
  • getState:获取 state 状态
  • setState:设置 state 状态
  • compareAndSetState:cas 机制设置 state 状态(防止多个线程同时设置 state 状态)
  • 独占模式是只有一个线程能够访问资源,而共享模式可以允许多个线程访问资源
  • 提供了基于 FIFO 的等待队列,类似于 Monitor 的 EntryList
  • 条件变量来实现等待、唤醒机制,支持多个条件变量,类似于 Monitor 的 WaitSet

★ 子类主要实现下面的方法(默认抛出 UnsupportedOperationException)

tryAcquire

tryRelease

tryAcquireShared

tryReleaseShared

isHeldExclusively

// 如果获取锁失败
if (!tryAcquire(arg)) {
   // 入队, 可以选择阻塞当前线程 park unpark
}
// 如果释放锁成功
if (tryRelease(arg)) {
  // 让阻塞线程恢复运行(唤醒阻塞的线程)
}

二、自定义锁

@Slf4j(topic = "Test1AQS")
public class Test1AQS {
    private static final MyLock MY_LOCK = new MyLock();
    public static void main(String[] args) {
        t4();
    }
    private static void t3() {
        new Thread(() -> {
            boolean isAcquire = false;
            try {
                isAcquire = MY_LOCK.tryLock(2000, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                if (isAcquire) {
                    log.debug("t3() t1 1");
                    Thread.sleep(2000);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                if (isAcquire) {
                    log.debug("t3() t1 2");
                    MY_LOCK.unlock();
                }
            }
        }, "t1").start();
        new Thread(() -> {
            boolean isAcquire = false;
            try {
                isAcquire = MY_LOCK.tryLock(2000, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                if (isAcquire) {
                    log.debug("t3() t2 1");
                }
            } finally {
                if (isAcquire) {
                    log.debug("t3() t2 2");
                    MY_LOCK.unlock();
                }
            }
        }, "t2").start();
    }
    private static void t2() {
        new Thread(() -> {
            boolean isAcquire = MY_LOCK.tryLock();
            try {
                if (isAcquire) {
                    log.debug("t2() t1 1");
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                if (isAcquire) {
                    log.debug("t2() t1 2");
                    MY_LOCK.unlock();
                }
            }
        }, "t1").start();
        new Thread(() -> {
            boolean isAcquire = MY_LOCK.tryLock();
            try {
                if (isAcquire) {
                    log.debug("t2() t2 1");
                }
            } finally {
                if (isAcquire) {
                    log.debug("t2() t2 2");
                    MY_LOCK.unlock();
                }
            }
        }, "t2").start();
    }
    private static void t1() {
        new Thread(() -> {
            MY_LOCK.lock();
            try {
                log.debug("t1 1");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                log.debug("t1 2");
                MY_LOCK.unlock();
            }
        }, "t1").start();
        new Thread(() -> {
            MY_LOCK.lock();
            try {
                log.debug("t2 1");
            } finally {
                log.debug("t2 2");
                MY_LOCK.unlock();
            }
        }, "t2").start();
    }
    private static void t4() {
        new Thread(() -> {
            log.debug("lock t4()");
            // 不可重入
            MY_LOCK.lock();
            MY_LOCK.lock();
            try {
                log.debug("t4() t1 1");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                log.debug("t4() t1 2");
                MY_LOCK.unlock();
            }
        }, "t1").start();
    }
}
class MyLock implements Lock {
    private MySync sync = new MySync();
    private static class MySync extends AbstractQueuedSynchronizer {
        /**
         * 尝试获取锁
         */
        @Override
        protected boolean tryAcquire(int arg) {
            // 获取成功
            if (compareAndSetState(0, 1)) {
                // 设置互斥锁的拥有线程为当前线程
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }
        /**
         * 尝试释放锁
         */
        @Override
        protected boolean tryRelease(int arg) {
            // 设置互斥锁的拥有线程为 null
            setExclusiveOwnerThread(Thread.currentThread());
            // setState(0)放在setExclusiveOwnerThread()下面
            // 可防止指令重排序(写屏障)
            setState(0);
            return true;
        }
        /**
         * 是否持有互斥锁
         */
        @Override
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }
        /**
         * 获取条件变量
         */
        protected Condition newCondition() {
            return new ConditionObject();
        }
    }
    /**
     * 获取锁
     * 若获取失败(进入等待队列)
     * 不可打断
     */
    @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();
    }
}
相关文章
|
安全 Java
【深入理解同步器AQS】
【深入理解同步器AQS】
126 0
|
7月前
|
安全 Java
利用AQS(AbstractQueuedSynchronizer)实现一个线程同步器
利用AQS(AbstractQueuedSynchronizer)实现一个线程同步器
|
7月前
|
存储 设计模式 安全
理解 AQS 和 ReentrantLock
在多线程编程中,同步机制是确保线程安全的关键。AQS(AbstractQueuedSynchronizer)和ReentrantLock是Java中两种常见的同步机制,它们各自具有不同的特性和适用场景。了解和掌握这两种机制对于编写高效、安全的并发程序至关重要。这篇文章将带你取了解和掌握这两种机制!另外值得一提的是:公平锁的实现与非公平锁是很像的,只不过在获取锁时不会直接尝试使用CAS来获取锁。只有当队列没节点并且state为0时才会去获取锁,不然都会把当前线程放到队列中。
175 1
|
Java C++
什么是AQS?
AQS(AbstractQueuedSynchronizer)是Java中的一个同步器框架
446 1
|
算法 Java
了解AQS
了解AQS
89 0
|
计算机视觉
AQS
AQS
88 0
|
存储 安全
AQS
一、为什么需要AQS?以及AQS的作用和重要性? AQS(AbstractQueuedSynchronizer)的重要性 AQS被用在ReentrantLock、ReentrantReadWriteLock、Semaphore、CountDownLatch、ThreadPoolExcutor的Worker中都有运用(JDK1.8)。AQS是这些类的底层原理,JUC包里很多重要的工具类背后都离不开AQS框架。
135 0
|
设计模式 安全 Java
【AQS】
【AQS】
124 0
【AQS】
|
算法 Java Linux
AQS这样学就很简单了
哈喽,我是子牙。十余年技术生涯,一路披荆斩棘从技术小白到技术总监到JVM专家到创业。技术栈如汇编、C语言、C++、Windows内核、Linux内核。特别喜欢研究虚拟机底层实现,对JVM有深入研究。分享的文章偏硬核,很硬的那种。
126 0
AQS这样学就很简单了