AQS和同步器工具类

一、 同步框架AbstractQueuedSynchronizer

Java并发编程核心在于java.concurrent.util包
而juc当中的大多数同步器实现都是围绕着共同的基础行为,比如等待队列、条件队列、独占获取、共享获取等,而这个行为的抽象就是基于AbstractQueuedSynchronizer简称AQS,AQS定义了一套多线程访问共享资源的同步器框架,是一个依赖状态(state)的同步器,主要结构是双向链表,如果线程抢不到,就进这个链表排队,之后再等待被唤醒;

AQS具备特性
1、阻塞等待队列
2、共享/独占
3、公平/非公平
4、可重入
5、允许中断

二、并发编程包依赖于AQS的内部实现

Java.concurrent.util当中同步器的实现如Lock,Latch,Barrier等,都是基于AQS框架实现
一般通过定义内部类Sync继承AQS,将同步器所有调用都映射到Sync对应的方法

三、AQS框架-管理状态

1、AQS内部维护属性volatile int state (32位)
state表示资源的可用状态

2、State三种访问方式
getState()、setState()、compareAndSetState()

3、AQS定义两种资源共享方式
Exclusive-独占,只有一个线程能执行,如ReentrantLock
Share-共享,多个线程可以同时执行,如Semaphore/CountDownLatch

4、AQS定义两种队列
同步等待队列
条件等待队列

四、ReentrantLock

这里 state 代表 :同一线程占用的次数
应用场景:
虽然允许多个线程进行访问,但是通过state机制保证同一时刻只有一个线程能获取资源。
可以替代synchronized关键字,提供更灵活的加锁和解锁操作,支持公平性和非公平性,可重入。

底层原理:
支持可重入性:reentrantLock.lock(); 同一个线程可用多次,每一次state就加1;同理reentrantLock.unlock(); 每次给state 减1,减到0就允许其他线程来抢。
state>0 代表有锁状态,state=0代表无锁状态;

任务开始前调用 reentrantLock.lock(); state就加1,表示同个线程占用的次数
任务结束后调用 reentrantLock.unlock(); state就减1

public static void print() {
        reentrantLock.lock(); //给state 加1
        System.out.println(Thread.currentThread().getName());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
           reentrantLock.unlock(); //给state 减1
        }
    }

源码中这一段取决了锁是不是 可重入的

//源码中,这里会判断是不是当前线程在获取资源,是的话就加起来,再set;
//而其他不可重入的锁没有这个逻辑,甚至不用去记录是不是当前线程获取的,所以不可重入
else if (current == getExclusiveOwnerThread()) {
    int nextc = c + acquires;
    if (nextc < 0) throw new Error("Maximum lock count exceeded");
    setState(nextc);
    return true;
}

五、 CountDownLatch

这里 state 代表 :还有多少线程能拿到资源,资源被拿走后不还回去,一次性

static CountDownLatch countDownLatch = new CountDownLatch(5);
新建时,初始化state = 某值 ;
每个线程完成任务后,调用 CountDownLatch.countDown() 将state减1
调用 CountDownLatch.await() 的主线程会被阻塞,直到state 减到0,也就是所有任务完成了,主线程才往下走;

六、Semaphore

这里 state 代表 :最多有多少线程同时能拿到资源,且资源被拿走后可以还回去给别的线程拿,动态变化

static Semaphore semaphore = new Semaphore(6);
新建时,初始化state = 某值 ;
任务开始前先调用semaphore.acquire() 给state 减1,表示占用了一个资源
任务完成后调用semaphore.release(); 给state 加1,表示把资源还回去
减到state = 0 时,则表示资源不够了,要抢的线程进队列排队

七、CyclicBarrier

这里 state 代表 :还有多少线程能拿到资源,但资源被拿走后统一在最后结束还回去,一波流
CyclicBarrier cyclicBarrier = new CyclicBarrier(7)
新建时,初始化state = 某值;
每次任务执行完调用cyclicBarrier.await(); state减1
减到state = 0 时,表示所有线程都干完活了,所有等待的线程继续执行,包括主线程。然后重新赋值 state=初始值;
允许一组线程互相等待,直到到达某个公共屏障点。

相关推荐

  1. AQS同步工具

    2024-06-18 23:36:02       26 阅读
  2. AES加密、解密工具

    2024-06-18 23:36:02       30 阅读
  3. HarmonyOS --@Prop@Link同步信息装饰

    2024-06-18 23:36:02       50 阅读
  4. Python装饰管理函数

    2024-06-18 23:36:02       74 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-18 23:36:02       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-18 23:36:02       106 阅读
  3. 在Django里面运行非项目文件

    2024-06-18 23:36:02       87 阅读
  4. Python语言-面向对象

    2024-06-18 23:36:02       96 阅读

热门阅读

  1. 微信小程序-路由和页面跳转API

    2024-06-18 23:36:02       30 阅读
  2. 算法设计与分析

    2024-06-18 23:36:02       32 阅读
  3. 定义仅限关键字参数

    2024-06-18 23:36:02       25 阅读
  4. NumPy 切片和索引

    2024-06-18 23:36:02       25 阅读
  5. 关于CSS

    关于CSS

    2024-06-18 23:36:02      29 阅读
  6. TOP150-LC121-买卖股票的最佳时机

    2024-06-18 23:36:02       32 阅读
  7. CSS 表单设计指南

    2024-06-18 23:36:02       31 阅读
  8. Samba服务访问异常分析处理

    2024-06-18 23:36:02       23 阅读
  9. 华为OD机试 C++ - 生日礼物

    2024-06-18 23:36:02       27 阅读