回忆录 java的AQS

回忆录 java的AQS

什么是AQS?

AQS 是 AbstractQueuedSynchronizer 的缩写,它是 Java 并发包中用于构建锁和其他同步器的基础框架。AQS 提供了一个灵活的框架,可以用于实现各种类型的锁和同步器

AbstractQueuedSynchronizer 都实现了哪些类型的锁呢?

  1. 独占锁(Exclusive Lock):

    • 独占锁是最常见的一种锁类型,它在任意时刻只允许一个线程持有锁,其他线程必须等待锁释放才能继续执行。ReentrantLockAbstractQueuedSynchronizer 的一个典型实现。
  2. 共享锁(Shared Lock):

    • 共享锁允许多个线程同时获取锁,从而允许并发访问共享资源。与独占锁不同,共享锁可能同时被多个线程持有。Java 并发包中的 ReadWriteLock 就是一个典型的共享锁,它提供了读锁和写锁,读锁可以被多个线程持有,但写锁只能被一个线程持有。
  3. 互斥锁(Mutex):

    • 互斥锁是一种特殊的独占锁,它在同一时刻只允许一个线程持有锁,其他线程必须等待。互斥锁通常用于保护临界区,防止多个线程同时访问共享资源。Java 中的 ReentrantLockReentrantReadWriteLock 都是互斥锁的实现。
  4. 公平锁(Fair Lock)和非公平锁(Nonfair Lock):

    • 公平锁和非公平锁都是独占锁,它们之间的区别在于获取锁的顺序。公平锁会按照线程请求锁的顺序进行获取,而非公平锁则允许某些线程插队获取锁。Java 中的 ReentrantLockReentrantReadWriteLock 都支持公平和非公平模式。

互斥锁和独占锁是同步机制中的两种不同类型的锁,它们有以下区别:

  1. 独占锁(Exclusive Lock):

    • 独占锁是一种锁类型,它在任意时刻只允许一个线程持有锁。当一个线程持有独占锁时,其他线程必须等待该线程释放锁后才能获取锁。独占锁通常用于保护对共享资源的互斥访问,防止多个线程同时修改共享资源导致数据不一致或丢失。Java 中的 ReentrantLock 就是一个典型的独占锁。
  2. 互斥锁(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);
    }

}

  

 
 

 

 
 
posted @ 2024-03-04 17:14  郎小乐  阅读(26)  评论(0)    收藏  举报