并发编程-Lock锁原理分析~

本文详细解析了Java并发编程中的ReentrantLock实现原理,包括公平锁和非公平锁的lock()方法实现,以及AbstractQueuedSynchronizer(AQS)在锁机制中的核心作用。通过分析源码,阐述了线程的互斥性和锁的重入特性,展示了锁的获取、释放以及线程等待队列的管理机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

并发安全性Lock锁及原理分析

以下是学习中的一些笔记记录,如果有错误希望得到你的指正~ 同时也希望对你有点帮助~

ReentrantLock

  • 重入锁、互斥锁
  • 满足线程的互斥性,意味着同一时刻,只允许一个线程进入到加锁的代码中
public class ReentrantLockTest {
    static int var = 0;
    static Lock lock = new ReentrantLock();

    public static void main(String[] args) {
        Thread one = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                inc();
            }
        }, "Thread-One");

        Thread two = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                inc();
            }
        }, "Thread-Two");

        one.start();
        two.start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(var);

    }

    static void inc(){
        lock.lock();
        var++;
        lock.unlock();
    }
}

ReentrantLock实现原理图
在这里插入图片描述

ThreadA线程调用lock()方法去尝试抢占锁,如果AQS中当前state状态为0,那么会使用CAS去修改AQS中state的值,并且exclusiveOwnerThread指向当前持有锁的线程。当ThreadB线程也去调用lock()方法尝试抢占锁时,发现此时AQS中state != 0,ThreadB将会封装成一个Node节点,并构建成一个双向链表进行排队等待,当ThreadA线程执行完毕,调用unlock()方法释放锁,将会唤醒AQS队列中head节点的下一个线程节点,锁的公平性与非公平性体现在释放锁的临界点,ThreadC线程抢占到了lock锁,在ThreadB线程抢到锁之前获得了锁

AbstractQueuedSynchronizer

AQS中实现了共享锁和互斥锁

  • 共享锁
  • 互斥锁
    • state 互斥量 0 和 >0,0表示无锁状态,state()状态的获取和修改
    • exclusiveOwnerThread 指向持有锁的线程
    • acquire(int arg)争抢锁的定义
    • tryAcquire(int acquires) 争抢锁定义,具体争抢锁逻辑由子类实现,例如 NonfairSyncFairSync
    • 线程Node节点的封装,阻塞线程节点实现

Lock.lock()

公平锁lock()实现

static final class FairSync extends Sync {

    final void lock() {
        //尝试争抢一把锁
        acquire(1);
    }
    
    //implement AbstractQueuedSynchronizer tryAcquire()
    protected final boolean tryAcquire(int acquires) {
        //记录当前争抢锁的线程
        final Thread current = Thread.currentThread();
        //获取当前AQS中的互斥量状态
        int c = getState();
        //无锁
        if (c == 0) {
            //公平锁上来就会判断AQS中是否存在线程节点排队,如果没有线程节点排队,接着尝试使用CAS去修改state值,修改成功表示抢占锁成功返回true
            if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) {
                //设置锁持有线程
                setExclusiveOwnerThread(current);
                return true;
            }
            //有锁再判断是否持有锁的线程是否是当前线程,重入
        } else if (current == getExclusiveOwnerThread()) {
            //这里互斥量的修改不需要使用CAS,因为当前线程已持有锁
            int nextc = c + acquires;
            if (nextc < 0) {
                throw new Error("Maximum lock count exceeded");
            }
            //修改互斥量,重入次数
            setState(nextc);
            return true;
        }
        //抢占锁失败,并不是持有锁线程,返回false
        return false;
    }
}

非公平锁lock()实现

static final class NonfairSync extends Sync {

    final void lock() {
        //非公平锁一上来就会去争抢一次锁
        if (compareAndSetState(0, 1)) {
            setExclusiveOwnerThread(Thread.currentThread());
        } else {
            //没有争抢到锁,再尝试争抢锁
            acquire(1);
        }
    }

    protected final boolean tryAcquire(int acquires) {
        return nonfairTryAcquire(acquires);
    }

    final boolean nonfairTryAcquire(int acquires) {
        final Thread current = Thread.currentThread();
        int c = getState();
        //无锁
        if (c == 0) {
            //再次尝试抢占锁
            if (compareAndSetState(0, acquires)) {
                setExclusiveOwnerThread(current);
                return true;
            }
        } else if (current == getExclusiveOwnerThread()) {
            //重入
            int nextc = c + acquires;
            if (nextc < 0) { // overflow
                throw new Error("Maximum lock count exceeded");
            }
            //同步state
            setState(nextc);
            return true;  
        }
        return false;
    }

}

公共逻辑

class AbstractQueuedSynchronizer {
    public final void acquire(int arg) {
        //抢占锁失败,接着执行 
        //addWaiter(Node.EXCLUSIVE)  封装当前线程为一个Node节点,并构建为一个双向链表
        //acquireQueued(addWaiter(Node.EXCLUSIVE), arg) 尝试争抢锁成功返回false,线程节点排队阻塞返回 true
       if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) {
          //中断当前阻塞的线程
          selfInterrupt();
       }
    }

    
    private Node addWaiter(Node mode) {
        //将当前线程封装为Node节点
        Node node = new Node(Thread.currentThread(), mode);
        Node pred = tail;
        //当已经有线程节点排队的时候,tail节点此时为上一个线程节点
        if (pred != null) {
            //将当前线程节点指向上一个排队的线程节点
            node.prev = pred;
            //通过CAS将尾节点设置为当前线程节点,pred是上一个尾节点
            if (compareAndSetTail(pred, node)) {
                //上一个尾节点指向当前线程节点构成双向链表
                pred.next = node;
                //返回当前线程节点,也是排队的尾节点
                return node;
            }
        }
        //自旋处理构建线程节点
        enq(node);
        return node;
    }

    /**
    * 构建一个头节点和尾节点相互指向的双向链表
    *                    ----->
    *  head (new Node)          封装的线程节点(tail)
    *                    <-----  
    */
    private Node enq(final Node node) {
        for (;;) {
            //首次为null,第二次为初始化的head节点
            Node t = tail;
            if (t == null) { // Must initialize
                //通过CAS初始化一个head节点
                if (compareAndSetHead(new Node()))
                    tail = head;
            } else {
                //
                node.prev = t;
                //通过CAS将线程节点设置为 tail节点
                if (compareAndSetTail(t, node)) {
                    //head的next为线程节点
                    t.next = node;
                    return t;
                }
            }
        }
    }

    /**
    * @param node 当前线程封装后的节点
    * @param arg  1
    */
    final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                //获取当前线程节点的上一个节点
                final Node p = node.predecessor();
                //如果上一个节点是head节点,再次尝试抢占锁,抢占锁成功则返回 interrupted
                if (p == head && tryAcquire(arg)) {
                    //设置当前线程节点为head节点
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                //不止一个线程节点排队,阻塞当前线程节点
                if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) {
                    interrupted = true;
                }
            }
        } finally {
            if (failed) {
                cancelAcquire(node);
            }
        }
    }

    //通过LockSupport.park()阻塞抢占锁失败的线程
    private final boolean parkAndCheckInterrupt() {
        LockSupport.park(this);
        return Thread.interrupted();
    }

    //中断当前的被阻塞的线程
    static void selfInterrupt() {
        Thread.currentThread().interrupt();
    }

}

Lock.unlock()

class ReentrantLock {

    public void unlock() {
        //释放一把锁
        sync.release(1);
    }

    class Sync{
        protected final boolean tryRelease(int releases) {
            //获取互斥量state - 1
            int c = getState() - releases;
            //必须由持有锁的线程来释放锁
            if (Thread.currentThread() != getExclusiveOwnerThread()) {
                throw new IllegalMonitorStateException();
            }
            boolean free = false;
            if (c == 0) {
                free = true;
                //清空,没有线程持有锁
                setExclusiveOwnerThread(null);
            }
            //更改互斥量 state
            setState(c);
            return free;
        }
    }   

}

class AbstractQueuedSynchronizer{
    public final boolean release(int arg) {
        //tryRelease 正常释放锁 返回true
        if (tryRelease(arg)) {
            //获取AQS队列head节点
            Node h = head;
            //head节点不为空
            if (h != null && h.waitStatus != 0) {
                //调用unpark方法进行唤醒
                unparkSuccessor(h);
            }
            return true;
        }
        return false;
    }

    private void unparkSuccessor(Node node) {
        int ws = node.waitStatus;
        //在互斥锁中,ws小于0表示节点是可唤醒状态也就是SIGNAL状态的线程节点
        if (ws < 0) {
            //0默认状态,表示不属于AQS中定义的任何状态
            compareAndSetWaitStatus(node, ws, 0);
        }
        Node s = node.next;
        //ws大于0也就是CANCELLED状态,表示线程已经被销毁了,或者线程异常
        if (s == null || s.waitStatus > 0) {
            s = null;
            //移除AQS队列中的ws>0的线程节点
            for (Node t = tail; t != null && t != node; t = t.prev) {
                //重新指向可唤醒的线程节点
                if (t.waitStatus <= 0) {
                    s = t;
                }
            }
        }
        //唤醒封装在s节点中的Thread线程
        if (s != null) {
            LockSupport.unpark(s.thread);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值