LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 290|回复: 0

JAVA-ReentrantLock核心函数分析

[复制链接]
发表于 2024-1-21 23:58:45 | 显示全部楼层 |阅读模式
通过分析ReentrantLock的源码,可知对其操作都转化为对Sync对象的操作,由于Sync继承了AQS,所以基本上都可以转化为对AQS的操作。如将ReentrantLock的lock函数转化为对Sync的lock函数的调用,而具体会根据采用的策略(如公平策略或者非公平策略)的不同而调用到Sync的不同子类。所以可知,在ReentrantLock的背后,是AQS对其服务提供了支持,由于之前我们分析AQS的核心源码,遂不再累赘。下面还是通过例子来更进一步分析源码。# 示例分析# 公平锁import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class MyThread extends Thread {
    private Lock lock;
    public MyThread(String name, Lock lock) {
        super(name);
        this.lock = lock;
    }
   
    public void run () {
        lock.lock();
        try {
            System.out.println(Thread.currentThread() + " running");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } finally {
            lock.unlock();
        }
    }
}

public class AbstractQueuedSynchronizerDemo {
    public static void main(String[] args) throws InterruptedException {
        Lock lock = new ReentrantLock(true);
        
        MyThread t1 = new MyThread("t1", lock);        
        MyThread t2 = new MyThread("t2", lock);
        MyThread t3 = new MyThread("t3", lock);
        t1.start();
        t2.start();   
        t3.start();
    }
}
运行结果(某一次):Thread[t1,5,main] running
Thread[t2,5,main] running
Thread[t3,5,main] running
说明: 该示例使用的是公平策略,由结果可知,可能会存在如下一种时序。说明: 首先,t1线程的lock操作 -> t2线程的lock操作 -> t3线程的lock操作 -> t1线程的unlock操作 -> t2线程的unlock操作 -> t3线程的unlock操作。根据这个时序图来进一步分析源码的工作流程。t1线程执行lock.lock,下图给出了方法调用中的主要方法。说明: 由调用流程可知,t1线程成功获取了资源,可以继续执行。t2线程执行lock.lock,下图给出了方法调用中的主要方法。说明: 由上图可知,最后的结果是t2线程会被禁止,因为调用了LockSupport.park。t3线程执行lock.lock,下图给出了方法调用中的主要方法。说明: 由上图可知,最后的结果是t3线程会被禁止,因为调用了LockSupport.park。t1线程调用了lock.unlock,下图给出了方法调用中的主要方法。说明: 如上图所示,最后,head的状态会变为0,t2线程会被unpark,即t2线程可以继续运行。此时t3线程还是被禁止。t2获得cpu资源,继续运行,由于t2之前被park了,现在需要恢复之前的状态,下图给出了方法调用中的主要方法。说明: 在setHead函数中会将head设置为之前head的下一个结点,并且将pre域与thread域都设置为null,在acquireQueued返回之前,sync queue就只有两个结点了。t2执行lock.unlock,下图给出了方法调用中的主要方法。说明: 由上图可知,最终unpark t3线程,让t3线程可以继续运行。t3线程获取cpu资源,恢复之前的状态,继续运行。说明: 最终达到的状态是sync queue中只剩下了一个结点,并且该节点除了状态为0外,其余均为null。t3执行lock.unlock,下图给出了方法调用中的主要方法。说明: 最后的状态和之前的状态是一样的,队列中有一个空节点,头节点为尾节点均指向它。
------

原文链接:https://pdai.tech/md/java/thread/java-thread-x-lock-ReentrantLock.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表