当前位置:网站首页>aqs的学习
aqs的学习
2022-04-23 19:47:00 【Fairy要carry】
目录
概述:
通过继承它来实现父类的功能
获取锁:
阻塞和获取资源用的是park和unpark;
释放锁:
判断是否有锁资源:
AbstractQueuedSynchronizer公有方法(AQS)
1.acquire:独占式获取同步状态;
2.release:独占式释放同步状态;
3.acquireShared(int arg):
共享式获取同步状态,如果当前线程未获取到同步状态,那么就进队列等待——>与独占式的主要区别是在同一时刻可以有多个线程获取同步状态;
4.releaseShared(int arg):共享式释放同步状态;
需要由子类实现的保护方法
1.tryAcquire:独占式获取同步状态;——通过cas操作设置锁资源占有状态,并且对锁的Owner进行设置
2.tryRelease:独占式释放同步状态;
3.getState:返回锁状态
还有几个shared
其他方法
锁和同步器的区别
锁:面向使用者,定义了锁和使用者交互方式 ,隐藏了细节;
同步器:面向的是锁的实现者,简化了锁的实现方式;
锁和同步器很好的隔离了使用者和实现着所需要关注的领域;
自定义锁-独占锁
package com.example.juc.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;
import static java.lang.Thread.sleep;
/**
* @author diao 2022/4/23
*/
@Slf4j(topic = "c.TestAqs")
public class TestAqs {
public static void main(String[] args) {
MyLock lock = new MyLock();
new Thread(()->{
lock.lock();
log.debug("locking...");
lock.lock();//synchronized和ReentrantLock都是可重入
try {
log.debug("locking...");
sleep(1);
} 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();
}
}
//自定义锁(不可重入锁);可重入锁:拿到锁资源下次进入一样可以进入
class MyLock implements Lock{
//独占锁,AQS基于队列(同步器)
class MySync extends AbstractQueuedSynchronizer{
/*1.尝试获取锁资源*/
@Override
protected boolean tryAcquire(int arg) {
//因为可能会有多个线程竞争锁资源,所以要进行cas
if(compareAndSetState(0,1)){
//尝试将锁的owner设置为当前线程
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
/*2.尝试释放锁资源*/
@Override
protected boolean tryRelease(int arg) {
//这里需要注意顺序,setState有volatile字段
// 有读写屏障,前面的修改锁拥有资源对其他线程都可见
setExclusiveOwnerThread(null);
setState(0);
return true;
}
/*3.判断是否持有独占锁*/
@Override
protected boolean isHeldExclusively() {
return getState()==1;
}
public Condition newCondition(){
return new ConditionObject();
}
}
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中的tryRelease是不一样的
* 上面的只是改变锁的拥有者以及锁的state,但并不会唤醒被阻塞的线程
* release可唤醒阻塞线程
*/
sync.release(1);
}
@Override//返回条件变量
public Condition newCondition() {
return sync.newCondition();
}
}
如代码所示,独占锁实现了在同一时刻只能用一个线程获取到锁,而其他获取锁的线程只能在等待队列等待;
AQS小结
使用方式?
AQS主要是通过继承的方式,子类通过继承同步器并实现它的抽象方法->来管理同步状态;
如何管理同步状态?
AQS使用一个int类型的成员变量state来表示同步状态,当state>0时表示已经获取了锁,当state = 0时表示释放了锁。它提供了三个方法(getState()、setState(int newState)、compareAndSetState(int expect,int update))来对同步状态state进行操作,当然AQS可以确保对state的操作是安全的。
特点:
AQS通过内置的FIFO同步队列来完成资源获取线程的排队工作,如果当前线程获取同步状态失败时,AQS则会将当前线程以及等待状态等信息构造成一个节点(Node)并将其加入同步队列,同时会阻塞当前线程;
站在使用角度,我理解其实就两个功能:独占和共享,要么独占要么共享,然后调用底层api;
AQS的大致实现思路
AQS内部维护了一个CLH队列来管理锁。线程会首先尝试获取锁,如果失败就将当前线程及等待状态等信息包装成一个node节点加入到同步队列sync queue里。 接着会不断的循环尝试获取锁(自旋),条件是当前节点为head的直接后继才会尝试。如果失败就会阻塞自己直到自己被唤醒。而当持有锁的线程释放锁的时候,会唤醒队列中的后继线程。
CLH(Craig,Landin,and Hagersten)队列是一个虚拟的双向队列(虚拟的双向队列即不存在队列实例,仅存在结点之间的关联关系)。AQS是将每条请求共享资源的线程封装成一个CLH锁队列的一个结点(Node)来实现锁的分配。
版权声明
本文为[Fairy要carry]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_57128596/article/details/124364671
边栏推荐
- Decompile and get the source code of any wechat applet - just read this (latest)
- Physical meaning of FFT: 1024 point FFT is 1024 real numbers. The actual input to FFT is 1024 complex numbers (imaginary part is 0), and the output is also 1024 complex numbers. The effective data is
- Inject Autowired fields into ordinary beans
- OpenHarmony开源开发者成长计划,寻找改变世界的开源新生力!
- 如何在BNB鏈上創建BEP-20通證
- 【webrtc】Add x264 encoder for CEF/Chromium
- @Mapperscan and @ mapper
- Vericrypt file hard disk encryption tutorial
- Steps to build a deep learning environment GPU
- Go modules daily use
猜你喜欢
Distinction between pointer array and array pointer
【webrtc】Add x264 encoder for CEF/Chromium
RuntimeError: Providing a bool or integral fill value without setting the optional `dtype` or `out`
Building googlenet neural network based on pytorch for flower recognition
[报告] Microsoft :Application of deep learning methods in speech enhancement
Garbage collector and memory allocation strategy
Command - sudo
[webrtc] add x264 encoder for CEF / Chromium
[report] Microsoft: application of deep learning methods in speech enhancement
Zero cost, zero foundation, build profitable film and television applet
随机推荐
Possible root causes include a too low setting for -Xss and illegal cyclic inheritance dependencies
MySQL lock
How to use go code to compile Pb generated by proto file with protoc Compiler Go file
ESP8266-入门第一篇
IIS data conversion problem: 16bit to 24bit
Mysql database - connection query
C6748 software simulation and hardware test - with detailed FFT hardware measurement time
[report] Microsoft: application of deep learning methods in speech enhancement
MySQL syntax collation (5) -- functions, stored procedures and triggers
[报告] Microsoft :Application of deep learning methods in speech enhancement
Possible root causes include a too low setting for -Xss and illegal cyclic inheritance dependencies
Hot reload debugging
Shanda Wangan shooting range experimental platform project - personal record (IV)
Mfcc: Mel frequency cepstrum coefficient calculation of perceived frequency and actual frequency conversion
MySQL数据库 - 单表查询(三)
Introduction to electron tutorial 3 - process communication
Easy mock local deployment (you need to experience three times in a crowded time. Li Zao will do the same as me. Love is like a festival mock)
Compact CUDA tutorial - CUDA driver API
Project training of Software College of Shandong University - Innovation Training - network security shooting range experimental platform (VII)
Data analysis learning directory