首页 > 编程语言 >20230608 java.util.concurrent.locks.ReentrantLock

20230608 java.util.concurrent.locks.ReentrantLock

时间:2023-08-22 17:44:48浏览次数:41  
标签:reentrantLock java Thread ReentrantLock System locks println out

介绍

  • java.util.concurrent.locks.ReentrantLock
  • public class ReentrantLock implements Lock, java.io.Serializable
  • ReentrantLock 是使用 AQS 的标准范式

API

构造器

  • ReentrantLock()
  • ReentrantLock(boolean fair)
    • fair :是否公平锁,默认非公平锁

public

实现接口 java.util.concurrent.locks.Lock

  • lock
  • lockInterruptibly
  • tryLock
  • tryLock
  • unlock
  • newCondition

其他 public

  • getHoldCount
    • 当前线程持有此锁的次数,如果此锁未被当前线程持有,则为零
  • isHeldByCurrentThread
    • 查询此锁是否由当前线程持有
  • isLocked
    • 查询此锁是否被任何线程持有
    • 此方法设计用于监视系统状态,而不用于同步控制
  • isFair
    • 是否公平锁
  • hasQueuedThreads
    • final boolean hasQueuedThreads()
    • 查询是否有任何线程正在等待获取此锁
    • 注意,因为取消可能随时发生,所以true返回并不能保证任何其他线程都会获得此锁。此方法主要用于监视系统状态。
  • hasQueuedThread
    • final boolean hasQueuedThread(Thread thread)
    • 查询入参线程是否正在等待获取此锁
  • getQueueLength
    • int getQueueLength()
    • 返回等待获取此锁的线程数的估计值
    • 该值只是一个估计值,因为当此方法遍历内部数据结构时,线程数可能会动态变化。此方法设计用于监视系统状态,而不用于同步控制
  • hasWaiters
    • boolean hasWaiters(Condition condition)
    • 查询是否有任何线程正在等待与此锁关联的 Condition
    • 注意,由于超时和中断可能随时发生,因此true返回并不能保证未来的signal会唤醒任何线程。此方法主要用于监视系统状态。
  • getWaitQueueLength
    • int getWaitQueueLength(Condition condition)
    • 返回等待与此锁关联的 Condition 的线程数的估计值

代码理解

ReentrantLock 实现 Lock 接口,内部锁实现使用 AQS AbstractQueuedSynchronizer

读代码时,需要关联 AbstractQueuedSynchronizer 一起读

包含三个静态内部类,分别是

  • abstract static class Sync extends AbstractQueuedSynchronizer
  • static final class NonfairSync extends Sync
  • static final class FairSync extends Sync

定义同步器:

private final Sync sync;

AbstractQueuedSynchronizer.stateReentrantLock 中代表的是线程持有锁的次数

公平锁

公平锁的实现对比 FairSyncNonfairSync ,区别在于

  • initialTryLock
  • tryAcquire

这两个方法都在 ReentrantLock#lock 方法调用中用到,两者实现的区别是 FairSync 在设置 state 前会调用 hasQueuedPredecessors 判断是否有任何线程等待获取的时间比当前线程长

ReentrantLock#tryLock 始终是非公平的

示例代码

用于调试理解的示例代码:

package study.hwj.v1p12.lock;

import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

/**
 * TestReentrantLock
 *
 * @author owenwjhuang
 * @date 2023/6/8
 */
public class TestReentrantLock {
    public static void main(String[] args) throws InterruptedException {
        // testTryLock();
        // testSingleThread();

        testTwoThread();

        // testThreeThread();

    }

    private static void testThreeThread() {
        ReentrantLock reentrantLock = new ReentrantLock();

        Runnable runnable = () -> {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
            System.out.println(Thread.currentThread() + ":11:" + reentrantLock);
            reentrantLock.lock();
            System.out.println(Thread.currentThread() + ":12:" + reentrantLock);
        };

        Thread thread1 = new Thread(runnable, "111");
        Thread thread2 = new Thread(runnable, "222");

        System.out.println(Thread.currentThread() + ":00:" + reentrantLock);
        reentrantLock.lock();
        System.out.println(Thread.currentThread() + ":01:" + reentrantLock);

        thread1.start();
        thread2.start();

        Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();
        allStackTraces.forEach((k, v) -> {
            System.out.println("==============");
            System.out.println(k);
            System.out.println(Arrays.toString(v));
        });


    }

    /**
     * 单个线程
     */
    private static void testTwoThread() throws InterruptedException {
        ReentrantLock reentrantLock = new ReentrantLock();

        new Thread(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println(Thread.currentThread().getName());
            reentrantLock.lock();

            reentrantLock.unlock();
        }).start();

        Thread.sleep(1000);
        System.out.println(Thread.currentThread().getName());

        reentrantLock.lock();

        Thread.sleep(100000);
        reentrantLock.unlock();

    }


    /**
     * 单个线程
     */
    private static void testSingleThread() {
        ReentrantLock reentrantLock = new ReentrantLock();

        System.out.println("1::" + reentrantLock);
        reentrantLock.lock();
        System.out.println("2::" + reentrantLock);
        reentrantLock.lock();
        System.out.println("3::" + reentrantLock);
        reentrantLock.unlock();
        System.out.println("4::" + reentrantLock);
    }

    private static void testTryLock() {
        ReentrantLock reentrantLock = new ReentrantLock();

        System.out.println("1::" + reentrantLock);
        boolean b1 = reentrantLock.tryLock();
        System.out.println("b1::" + b1);
        System.out.println("2::" + reentrantLock);
        boolean b2 = reentrantLock.tryLock();
        System.out.println("b2::" + b2);
        System.out.println("3::" + reentrantLock);
        reentrantLock.unlock();
        System.out.println("4::" + reentrantLock);
    }
}

标签:reentrantLock,java,Thread,ReentrantLock,System,locks,println,out
From: https://www.cnblogs.com/huangwenjie/p/17649193.html

相关文章

  • 20230614 java.util.concurrent.atomic.AtomicInteger
    介绍java.util.concurrent.atomic.AtomicIntegerpublicclassAtomicIntegerextendsNumberimplementsjava.io.SerializableAPI构造器AtomicInteger()AtomicInteger(intinitialValue)设置初始值,默认是0public方法get,set原子操作不同步内存屏障,不能......
  • 20230615 java.lang.invoke.VarHandle
    介绍java.lang.invoke.VarHandlepublicabstractclassVarHandleimplementsConstable在并发编程和底层内存访问上提供了一种更为灵活、安全和高效的方式APIget,set保证原子性getVolatile,setVolatile保证可见性getOpaque,setOpaque保证有序性op......
  • 20230615 java.lang.ThreadLocal
    介绍java.lang.ThreadLocalpublicclassThreadLocal线程局部变量APIstatic方法withInitial<S>ThreadLocal<S>withInitial(Supplier<?extendsS>supplier)创建一个线程局部变量,其初始值通过调用给定的supplier生成public方法get得到这个线程的当前值......
  • java应用接口自动化覆盖率统计实践
    一、背景Java应用接口自动化覆盖率统计的意义在于:确保测试覆盖率:通过自动化覆盖率统计,可以确保测试用例对应用程序的各个接口进行了全面的覆盖。这有助于发现潜在的代码错误、逻辑漏洞或者未处理的异常情况。提高代码质量:通过自动化覆盖率统计,可以发现代码中未被测试到的部......
  • java-sdk接口测试覆盖率统计实践
    一、背景接口覆盖率统计在JavaSDK开发中具有重要的意义。它衡量了代码中接口被测试用例覆盖的程度,即测试用例对接口的执行情况进行了多少次验证。接口覆盖率统计的意义包括:质量保证:接口覆盖率统计可以帮助开发团队评估测试的全面性和质量,确保代码的正确性和稳定性。高覆盖率......
  • Java中怎么进行原子操作?
    在Java中进行原子操作,特别是替换某个属性,你可以使用AtomicReference类来实现。AtomicReference可以保证对对象引用的原子更新操作。以下是一个示例,展示如何使用AtomicReference来进行原子替换操作:javaCopycodeimportjava.util.concurrent.atomic.AtomicReference;publ......
  • java实现大文件上传技术
    ​ 1,项目调研因为需要研究下断点上传的问题。找了很久终于找到一个比较好的项目。 在GoogleCode上面,代码弄下来超级不方便,还是配置hosts才好,把代码重新上传到了github上面。 https://github.com/freewebsys/java-large-file-uploader-demo 效果: 上传中,显示进度,时间......
  • 让Android Studo 不编译某个Java文件
    有时为了调试,让某些文件暂时不需编译,这样可以排除错误带来的无法运行情况,可以在build.gradle中加入:excludes=['com.coolweather.myble/AddrInterceptor.java'],如下compileOptions{sourceCompatibilityJavaVersion.VERSION_1_8targetCompatibilityJavaVers......
  • 15 JavaScript ES6中的箭头函数
    15JavaScriptES6中的箭头函数什么是箭头函数ES6中允许使用=>来定义函数。箭头函数相当于匿名函数,并简化了函数定义。基本语法//箭头函数letfn=(name)=>{//函数体return`Hello${name}!`;};//等同于letfn=function(name){//函数体......
  • Javascript关于对象的理解
    对象的概念  对象是一个包含数据和方法的集合。  下面,我们通过实例探索对象。首先,创建一个对象varperson={};  如果在控制台输入person,将会得到 [objectObject] 这时,我们就创建了一个空的对象,接着,我们需要向空对象中添加数据或方法varperson={name:[......