回忆录 java的AQS
回忆录 java的AQS
什么是AQS?
AQS 是 AbstractQueuedSynchronizer 的缩写,它是 Java 并发包中用于构建锁和其他同步器的基础框架。AQS 提供了一个灵活的框架,可以用于实现各种类型的锁和同步器
AbstractQueuedSynchronizer 都实现了哪些类型的锁呢?
-
独占锁(Exclusive Lock):
- 独占锁是最常见的一种锁类型,它在任意时刻只允许一个线程持有锁,其他线程必须等待锁释放才能继续执行。
ReentrantLock是AbstractQueuedSynchronizer的一个典型实现。
- 独占锁是最常见的一种锁类型,它在任意时刻只允许一个线程持有锁,其他线程必须等待锁释放才能继续执行。
-
共享锁(Shared Lock):
- 共享锁允许多个线程同时获取锁,从而允许并发访问共享资源。与独占锁不同,共享锁可能同时被多个线程持有。Java 并发包中的
ReadWriteLock就是一个典型的共享锁,它提供了读锁和写锁,读锁可以被多个线程持有,但写锁只能被一个线程持有。
- 共享锁允许多个线程同时获取锁,从而允许并发访问共享资源。与独占锁不同,共享锁可能同时被多个线程持有。Java 并发包中的
-
互斥锁(Mutex):
- 互斥锁是一种特殊的独占锁,它在同一时刻只允许一个线程持有锁,其他线程必须等待。互斥锁通常用于保护临界区,防止多个线程同时访问共享资源。Java 中的
ReentrantLock和ReentrantReadWriteLock都是互斥锁的实现。
- 互斥锁是一种特殊的独占锁,它在同一时刻只允许一个线程持有锁,其他线程必须等待。互斥锁通常用于保护临界区,防止多个线程同时访问共享资源。Java 中的
-
公平锁(Fair Lock)和非公平锁(Nonfair Lock):
- 公平锁和非公平锁都是独占锁,它们之间的区别在于获取锁的顺序。公平锁会按照线程请求锁的顺序进行获取,而非公平锁则允许某些线程插队获取锁。Java 中的
ReentrantLock和ReentrantReadWriteLock都支持公平和非公平模式。
- 公平锁和非公平锁都是独占锁,它们之间的区别在于获取锁的顺序。公平锁会按照线程请求锁的顺序进行获取,而非公平锁则允许某些线程插队获取锁。Java 中的
互斥锁和独占锁是同步机制中的两种不同类型的锁,它们有以下区别:
-
独占锁(Exclusive Lock):
- 独占锁是一种锁类型,它在任意时刻只允许一个线程持有锁。当一个线程持有独占锁时,其他线程必须等待该线程释放锁后才能获取锁。独占锁通常用于保护对共享资源的互斥访问,防止多个线程同时修改共享资源导致数据不一致或丢失。Java 中的
ReentrantLock就是一个典型的独占锁。
- 独占锁是一种锁类型,它在任意时刻只允许一个线程持有锁。当一个线程持有独占锁时,其他线程必须等待该线程释放锁后才能获取锁。独占锁通常用于保护对共享资源的互斥访问,防止多个线程同时修改共享资源导致数据不一致或丢失。Java 中的
-
互斥锁(Mutex):
- 互斥锁是一种特殊的独占锁,它在同一时刻只允许一个线程持有锁,其他线程必须等待。互斥锁通常用于保护临界区,防止多个线程同时访问共享资源。互斥锁的概念来源于操作系统领域,在多线程编程中通常用来描述一种同步机制。在操作系统中,互斥锁用于保护共享资源,防止并发访问导致数据破坏或不一致。在 Java 中,独占锁就是一种互斥锁。
总的来说,独占锁是一种广义上的锁类型,而互斥锁是独占锁的一种特殊形式。互斥锁通常用于描述一种同步机制,用来保护对共享资源的互斥访问,而独占锁则可以用来实现各种不同的同步需求,如互斥访问、临界区保护、顺序控制等。
代码案例1编写一个独占锁并且非公平锁案例
package com.test.dockerwebdemo.aqs;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
public class MyAQS非公平锁 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) {
setExclusiveOwnerThread(null);
setState(0);//0应该是释放锁
return true;
}
//判断是否处于占用状态
protected boolean isHeldExclusively(){
return getState()==1;
}
//公共方法获取锁
public void lock(){
acquire(1);
}
public void unlook(){
release(1);
}
//公共方法释放锁
}
代码案例2编写一个独占锁并且公平锁案例
package com.test.dockerwebdemo.aqs;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.LockSupport;
public class MyAQS独占公平锁 extends AbstractQueuedSynchronizer {
// 等待队列,用于记录等待获取锁的线程
private final ConcurrentLinkedQueue<Thread> waiters = new ConcurrentLinkedQueue<>();
// 尝试获取同步状态
@Override
protected boolean tryAcquire(int arg) {
// 获取同步状态成功的条件
if (compareAndSetState(0, 1)) {
// 设置当前线程为独占线程
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
// 尝试释放同步状态
@Override
protected boolean tryRelease(int arg) {
setExclusiveOwnerThread(null);
setState(0); // 0应该是释放锁
return true;
}
// 判断是否处于占用状态
protected boolean isHeldExclusively() {
return getState() == 1;
}
// 公共方法获取锁
public void lock() {
if (!tryAcquire(1)) {
// 获取同步状态失败,将当前线程加入等待队列,并且阻塞当前线程
waiters.add(Thread.currentThread());
for (;;) {
//阻塞当前线程
LockSupport.park(this);
if (tryAcquire(1) || Thread.currentThread().isInterrupted()) {
// 如果获取同步状态成功或者当前线程被中断,则退出循环
waiters.remove(Thread.currentThread());
return;
}
}
}
}
// 公共方法释放锁
public void unlock() {
if (tryRelease(1)) {
// 如果释放同步状态成功,则唤醒等待队列中的第一个线程
Thread first = waiters.peek();
if (first != null) {
//调用 LockSupport.unpark(thread) 方法会解除线程 thread 的阻塞状态,使其从 park() 方法返回,从而继续执行。
LockSupport.unpark(first);
}
}
}
}
代码案例3编写一个共享锁
package com.test.dockerwebdemo.aqs;
import com.sun.corba.se.impl.orbutil.concurrent.Sync;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.LockSupport;
public class MyAQS共享锁 extends AbstractQueuedSynchronizer {
// 写锁,state为0表示没有写锁,1表示有写锁
boolean isWriteLocked() {
return getState() == 1;
}
// 获取读锁
protected int tryAcquireShared(int unused) {
// 如果有写锁,或者有等待线程,获取读锁失败
if (isWriteLocked() || hasQueuedThreads())
return -1;
else
return 0; // 返回大于等于0的数表示获取读锁成功
}
// 释放读锁
protected boolean tryReleaseShared(int unused) {
return true; // 读锁可以直接释放
}
// 获取写锁
protected boolean tryAcquire(int unused) {
// 尝试获取写锁,成功返回true,失败返回false
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
// 释放写锁
protected boolean tryRelease(int unused) {
// 释放写锁
if (getState() == 0)
throw new IllegalMonitorStateException("Lock is not held");
setExclusiveOwnerThread(null);
setState(0);
return true;
}
// 同步器实例
private final MyAQS共享锁 sync = new MyAQS共享锁();
// 获取读锁
public void readLock() {
sync.acquireShared(0);
}
// 释放读锁
public void readUnlock() {
sync.releaseShared(0);
}
// 获取写锁
public void writeLock() {
sync.acquire(0);
}
// 释放写锁
public void writeUnlock() {
sync.release(0);
}
}
代码案例4编写一个重入锁
package com.test.dockerwebdemo.aqs;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
public class MyAQS独占重入锁 extends AbstractQueuedSynchronizer {
// 当前持有锁的线程
private Thread exclusiveOwnerThread;
// 构造函数
public MyAQS独占重入锁() {
setState(0);
exclusiveOwnerThread = null;
}
// 尝试获取锁
@Override
protected boolean tryAcquire(int arg) {
Thread currentThread = Thread.currentThread();
int state = getState();
if (state == 0) {
if (compareAndSetState(0, arg)) {
exclusiveOwnerThread = currentThread;
return true;
}
} else if (currentThread == exclusiveOwnerThread) {
setState(state + arg);
return true;
}
return false;
}
// 尝试释放锁
@Override
protected boolean tryRelease(int arg) {
if (Thread.currentThread() != exclusiveOwnerThread) {
throw new IllegalMonitorStateException();
}
int state = getState() - arg;
if (state == 0) {
exclusiveOwnerThread = null;
setState(state);
return true;
}
setState(state);
return false;
}
// 判断是否处于占用状态
protected boolean isHeldExclusively() {
return getState() != 0;
}
// 公共方法获取锁
public void lock() {
acquire(1);
}
// 公共方法释放锁
public void unlock() {
release(1);
}
}

浙公网安备 33010602011771号