LockSupport解析与使用

LockSupport与Condition解析 剖析了Java并发包中的两个核心线程协作工具:LockSupport和Condition。LockSupport基于Unsafe类提供底层的线程阻塞(park)和唤醒(unpark)机制,支持精确线程唤醒。Condition作为更强大的wait/notify替代方案,与Lock配合使用,具有独立等待队列、灵活唤醒方式和超时机制等优势。重点分析了ConditionObject的await方法实现,包括节点加入条件队列、锁释放、线程阻塞及唤醒后的锁竞争流程,并通过生产者-消费者模型展示了Conditi 阅读详情

 赛博朔方  枫叶     

      LockSupport提供park()和unpark()方法实现阻塞线程和解除线程阻塞,实现的阻塞和解除阻塞是基于”许可(permit)”作为关联,permit相当于一个信号量(0,1),默认是0. 线程之间不再需要一个Object或者其它变量来存储状态,不再需要关心对方的状态.

源码:
public class LockSupport {
    private LockSupport() {} // Cannot be instantiated.
    private static void setBlocker(Thread t, Object arg) {
        // Even though volatile, hotspot doesn't need a write barrier here.
        UNSAFE.putObject(t, parkBlockerOffset, arg);
    }
    public static void unpark(Thread thread) {
        if (thread != null)
            UNSAFE.unpark(thread);
    }
    public static void park(Object blocker) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        UNSAFE.park(false, 0L);
        setBlocker(t, null);
    }
    public static void parkNanos(Object blocker, long nanos) {
        if (nanos > 0) {
            Thread t = Thread.currentThread();
            setBlocker(t, blocker);
            UNSAFE.park(false, nanos);
            setBlocker(t, null);
        }
    }
    public static void parkUntil(Object blocker, long deadline) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        UNSAFE.park(true, deadline);
        setBlocker(t, null);
    }
    public static Object getBlocker(Thread t) {
        if (t == null)
            throw new NullPointerException();
        return UNSAFE.getObjectVolatile(t, parkBlockerOffset);
    }
    public static void park() {
        UNSAFE.park(false, 0L);
    }
    public static void parkNanos(long nanos) {
        if (nanos > 0)
            UNSAFE.park(false, nanos);
    }
    public static void parkUntil(long deadline) {
        UNSAFE.park(true, deadline);
    }
    static final int nextSecondarySeed() {
        int r;
        Thread t = Thread.currentThread();
        if ((r = UNSAFE.getInt(t, SECONDARY)) != 0) {
            r ^= r << 13;   // xorshift
            r ^= r >>> 17;
            r ^= r << 5;
        }
        else if ((r = java.util.concurrent.ThreadLocalRandom.current().nextInt()) == 0)
            r = 1; // avoid zero
        UNSAFE.putInt(t, SECONDARY, r);
        return r;
    }
    // Hotspot implementation via intrinsics API
    private static final sun.misc.Unsafe UNSAFE;
    private static final long parkBlockerOffset;
    private static final long SEED;
    private static final long PROBE;
    private static final long SECONDARY;
    static {
        try {
            UNSAFE = sun.misc.Unsafe.getUnsafe();
            Class<?> tk = Thread.class;
            parkBlockerOffset = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("parkBlocker"));
            SEED = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomSeed"));
            PROBE = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomProbe"));
            SECONDARY = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomSecondarySeed"));
        } catch (Exception ex) { throw new Error(ex); }
    }
}


从源码中得到初步信息:
1.不能被实例化(构造函数是私有的)

2.方法都是静态方法


成员变量:
UNSAFE
parkBlockerOffset
SEED
PROBE
SECONDARY

UNSAFE: 

JDK内部用的工具类, 可以直接操控内存,被JDK广泛用于自己的包中.它通过暴露一些Java意义上说“不安全”的功能给Java层代码,来让JDK能够更多的使用Java代码来实现一些原本是平台相关的、需要使用native语言(例如C或C++)才可以实现的功能。该类不应该在JDK核心类库之外使用。


parkBlockerOffset:
Class<?> tk = Thread.class;
            parkBlockerOffset = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("parkBlocker"));


解释起来就是:挂起线程对象的偏移地址,对应的是Thread类的parkBlocker.
/**
     * The argument supplied to the current call to
     * java.util.concurrent.locks.LockSupport.park.
     * Set by (private) java.util.concurrent.locks.LockSupport.setBlocker
     * Accessed using java.util.concurrent.locks.LockSupport.getBlocker
     */
    volatile Object parkBlocker;

可以看出这个对象是被LockSupport的setBlocker和getBlocker调用
 
这个对象是用来记录线程被阻塞时被谁阻塞的,用于线程监控和分析工具来定位原因的。


偏移量又拿来做什么呢?
parkBlockerOffset = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("parkBlocker"));
原来偏移量就算Thread这个类里面变量parkBlocker在内存中的偏移量:

JVM的实现可以自由选择如何实现Java对象的“布局“,也就是在内存里Java对象的各个部分放在哪里,包括对象的实例字段和一些元数据之类。 sun.misc.Unsafe里关于对象字段访问的方法把对象布局抽象出来,它提供了objectFieldOffset()方法用于获取某个字段相对 Java对象的“起始地址”的偏移量,也提供了getInt、getLong、getObject之类的方法可以使用前面获取的偏移量来访问某个Java 对象的某个字段。


 
获取当前线程,通过偏移量的方式设置parkBlocker的值,将调取unsafe.park把线程挂起,线程被恢复后,修改blocker为null


为什么要用偏移量来获取对象?干吗不要直接写个get,set方法?
      parkBlocker就是在线程处于阻塞的情况下才被赋值。线程都已经被阻塞了,如果不通过这种内存的方法,而是直接调用线程内的方法,线程是不会回应调用的。
SEED, PROBE, SECONDARY: 
/** The current seed for a ThreadLocalRandom */
    @sun.misc.Contended("tlr")
    long threadLocalRandomSeed;
/** Probe hash value; nonzero if threadLocalRandomSeed initialized */
    @sun.misc.Contended("tlr")
    int threadLocalRandomProbe;

  /** Secondary seed isolated from public ThreadLocalRandom sequence */
    @sun.misc.Contended("tlr")
    int threadLocalRandomSecondarySeed;
都是Thread类中的内存偏移地址,主要用于ThreadLocalRandom类进行随机数生成,它要比Random性能好很多,可阅读了解详情
 

核心函数

因为LockSupport的核心方法都是基于Unsafe类中的park和unpark方法

         
public native void park(boolean isAbsolute, long time);
public native void unpark(Thread thread);

park: 阻塞线程,线程在一下三种情况下会被堵塞:
    1.调用unpark方法,释放该线程的许可
    2.该线程被中断
    3.到期时间。
isAbsolute为true。
isAbsolute为false。当time为0时,表示无限等待,直到unpark发生。
unpark: 释放线程的堵塞,即修改信号量为1, 同时park返回。


1.调用一次unpark,
如果没有可用线程,则给定许可(permit就变成1(不会累计))
如果有线程被阻塞,接触锁,同时park返回.
如果给定线程没有启动,则该操作不能保证有任何效果.
2.调用park,则会检测permit是否为1;
如果为1则将permit变成0;
如果不为1,则堵塞线程,直到permit变为1.
3.park()和unpark()不会有“Thread.suspend和Thread.resume所可能引发的死锁” 问题,由于许可的存在,调用 park 的线程和另一个试图将其 unpark 的线程之间的竞争将保持活性。
4.如果调用线程被中断,则park方法会返回.
5.park 方法还可以在其他任何时间"毫无理由"地返回,因此通常必须在重新检查返回条件的循环里调用此方法。从这个意义上说,park 是“忙碌等待”的一种优化,它不会浪费这么多的时间进行自旋,但是必须将它与 unpark 配对使用才更高效
6.unpark方法可以先于park调用。比如线程1调用unpark给线程2发了一个“许可“,那么当线程2调用park时,发现已经有“许可”了,那么它会马上再继续运行
	public static void park();
	public static void park() {
        UNSAFE.park(false, 0L);// // 获取许可,设置时间为无限长,直到可以获取许可
    }	


调用了park方法后,会禁用当前线程,除非许可可用,在一下三种情况发生之前,线程处于阻塞状态:
1.其他某个线程将当前线程作为目标调用 unpark
2.其他某个线程中断当前线程
3.该调用不合逻辑地(即毫无理由地)返回
当前线程会获取许可,可以继续运行


public static void park(Object blocker);
public static void park(Object blocker) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        UNSAFE.park(false, 0L);
        setBlocker(t, null);
}


先获取当前线程,设置当前线程的parkBlocker字段(parkBlocker), 调用Unsafe类的park方法,最后再次调用setBlocker,为什么呢?
因为当前线程首先设置好parkBlocker字段后再调用Unsafe的park方法,之后,当前线程已经被阻塞,等待unpark方法被调用, unpark方法被调用,该线程获得许可后,可以继续进行下面的代码,第二个setBlocker参数parkBlocker字段设置为null,这样就完成了整个park方法的逻辑. 如果没有第二个setBlocker,那么之后没有调用park(Object blocker),而直接调用getBlocker方法,得到的还是前一个park(Object blocker)设置的blocker,显然是不符合逻辑的。 所以,park(Object) 方法里必须要调用setBlocker方法两次。
private static void setBlocker(Thread t, Object arg) {
        UNSAFE.putObject(t, parkBlockerOffset, arg);
}
public static void parkNanos(Object blocker, long nanos)
public static void parkNanos(Object blocker, long nanos) {
        if (nanos > 0) {
            Thread t = Thread.currentThread();
            setBlocker(t, blocker);
            UNSAFE.park(false, nanos);
            setBlocker(t, null);
        }
}


在解除堵塞之前禁用当前线程, 并最多等待指定的等待时间
public static void parkUntil(Object blocker, long deadline)
	public static void parkUntil(Object blocker, long deadline) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        UNSAFE.park(true, deadline);
        setBlocker(t, null);
    }

指定的时限前禁用当前线程,除非许可可用
public static void unpark(Thread thread)
	public static void unpark(Thread thread) {
        if (thread != null)
            UNSAFE.unpark(thread);
    }


线程在 park 上受阻塞,将解除其阻塞状态。否则,预发许可,下一次调用 park 不会受阻塞


LockSupport的park(),unPark()与Thread的wait(),notify()区别
    1.面向的主体不一样。LockSuport主要是针对Thread进进行阻塞处理,可以指定阻塞队列的目标对象,每次可以指定具体的线程唤醒。Object.wait()是以对象为纬度,阻塞当前的线程和唤醒单个(随机)或者所有线程。

    2.实现机制不同。虽然LockSuport可以指定monitor的object对象,但和object.wait(),两者的阻塞队列并不交叉。


代码:
public class LockSupportTest {
	public static void main(String[] args) throws Exception {
		TestLockSupport lockSupport = new TestLockSupport();
		lockSupport.start();
//		TestThread thread = new TestThread();
//		thread.start();
		
	}
}
class TestLockSupport extends Thread {
	public void run() {
		System.out.println( "TestLockSupport.run()" );
		LockSupport.park(  );
	}
}
class TestThread extends Thread {
	public void run() {
		System.out.println( "TestThread.run()" );
		synchronized (this) {
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}



使用jstack打印堆栈信息
LockSupport:
"Thread-0" #10 prio=5 os_prio=0 tid=0x000000001d6a5800 nid=0x2ad0 waiting on con
dition [0x000000001e1cf000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:304)
        at TestLockSupport.run(LockSupportTest.java:16)


可以看出当前线程状态时等待的,用的是Unsafe.park挂起的


Thread:
"Thread-0" #10 prio=5 os_prio=0 tid=0x000000001d321000 nid=0x8a8 in Object.wait(
) [0x000000001e2af000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x000000076b257698> (a TestThread)
        at java.lang.Object.wait(Object.java:502)
        at TestThread.run(LockSupportTest.java:23)
        - locked <0x000000076b257698> (a TestThread)


可以看出是用Object.wait实现的


从上面可以看出:
LockSupport阻塞和解除阻塞线程直接操作的是Thread,而Object的wait/notify它并不是直接对线程操作,它是被动的方法,它需要一个object来进行线程的挂起或唤醒.
Thead在调用wait之前, 当前线程必须先获得该对象的监视器(synchronized),被唤醒之后需要重新获取到监视器才能继续执行.而LockSupport可以随意进行park或者unpark. 

结论:

     Thread的notify也是在实际使用过程只需要斟酌的事情,notifyAll唤醒所有线程;notify唤醒单个线程,如果有两个被阻塞线程….

          LockSupport的park也可以响应Thread的interrupt中断,后面会有例子详讲.




案例
先park,后unpark
public class LockSupportTest {
	public static void main(String[] args) throws Exception {
		TestThread thread = new TestThread( Thread.currentThread() );
		thread.start();
		System.out.println( "before park" );
		// 等待获取许可
		LockSupport.park( "Park" );
		System.out.println( "after park" );
	}
}

class TestThread extends Thread {
	private Object object;
	public TestThread(Object object) {
		this.object = object;
	}
	public void run() {
		System.out.println( "before unpark" );
		// 休眠,保证setBlocker(t, blocker)
		try {
			Thread.sleep( 500 );
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		// 获取blocker
		System.out.println( "Blocker info: " + LockSupport.getBlocker( (Thread) object ) );
		// 释放许可
		LockSupport.unpark( (Thread) object );
		// 休眠500ms,保证先执行park中的setBlocker(t, null);
		try {
			Thread.sleep( 500 );
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println( "Blocker info: " + LockSupport.getBlocker( (Thread) object ) );
		System.out.println( "after unpark" );
	}
}


结果:
before park
before unpark
Blocker info Park
after park
Blocker info null
after unpark


先执行park,然后在执行unpark,进行同步,并且在unpark的前后都调用了getBlocker,可以看到两次的结果不一样,第二次调用的结果为null,这是因为在调用unpark之后,执行了Lock.park(Object blocker) 方法中的setBlocker(t, null) 方法,所以第二次调用getBlocker时为null


先unpark,后park
public class LockSupportTest {
	public static void main(String[] args) throws Exception {
		TestThread thread = new TestThread( Thread.currentThread() );
		long start = System.nanoTime();
		thread.start();
		try {
			Thread.sleep( 1000 );
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println( "before park" );
		// 等待获取许可
		LockSupport.park( "Park" );
		System.out.println( "after park:" + (System.nanoTime() - start) );
	}
}

class TestThread extends Thread {
	private Object object;
	public TestThread(Object object) {
		this.object = object;
	}
	public void run() {
		System.out.println( "before unpark" );
		LockSupport.unpark( (Thread) object );
		System.out.println( "after unpark" );
	}
}

before unpark
after unpark
before park
after park:3000046392



先执行unpark,在调用park,直接就没被阻塞, 因此park/unpark相比wait/notify更加的灵活


interrupt与unpark
public class LockSupportTest {
	public static void main(String[] args) throws Exception {
		TestThread thread = new TestThread();
		thread.start();
		try {
			Thread.sleep( 1000 );
		} catch (InterruptedException e) {
			e.printStackTrace();
		}		
		thread.interrupt();		
	}
}

class TestThread extends Thread {
	public void run() {
		System.out.println( Thread.currentThread().isInterrupted() );
		LockSupport.park();
		System.out.println( Thread.currentThread().isInterrupted() );
	}
}

false
true


可以看到子线程被阻塞后,主线程调用子线程中断,子线程则继续执行,并没有抛出InterruptedException, 这里依赖的是Interrupted status, 如果线程被中断而退出阻塞该状态会被修改为true, 可见interrupt起到的作用与unpark一样.


总结
简而言之:
1.实现机制和wait/notify有所不同,面向的是线程
2.不需要依赖监视器
3.与wait/notify没有交集
4.使用起来方便灵活



同一个线程池嵌套使用程序卡死问题排查 阅读详情

相关推荐

又一次Java线程卡死的调试经历

我的java代码,每天凌晨1点都会执行一个定时任务,定时任务中有循环执行的任务,每次循环都有开始和结束日志,某一天,我忽然发现,日志中前一天的循环只执行了几次就停止了,根据日志来看,执行到第4次循环的时候,只有开始的日志,没有结束的日志,那肯定是在里面卡死了 我首先执行 # ps -ef | grep tomcat 获取到了线程的pid 然后执行jstack # jstack -l 1...

u011734144的专栏 6万+

jstack命令及其死锁、CPU飙高问题排查使用

一、jstack用法 [root@smdw tang]# jstack Usage: jstack [-l] <pid> (to connect to running process) jstack -F [-m] [-l] <pid> (to connect to a hung process) jstack [...

IT- 研究者 3170

从零开始之stm32之CAN通信

CAN通信极简教程(小白友好版),从小白的视角了解并实现简单的STM32F103的CAN通信,直接上手。

qq_30993593的博客 1306

sun.misc.Unsafe.park(Native Method)异常

这里写自定义目录标题sun.misc.Unsafe.park(Native Method)异常,异常如下: sun.misc.Unsafe.park(Native Method)异常,异常如下: 2019/07/30-09:40:34 [localhost-startStop-1] WARN org.apache.catalina.loader.WebappClassLoaderBase - T...

weixin_41160551的博客 8万+

XC7K325T FPGA硬件设计实战:从板级原理图到高速接口优化

本文以XC7K325T FPGA为核心,详细阐述了从板级原理图设计到高速接口优化的完整硬件实战流程。内容涵盖芯片管脚与电源规划、时钟复位配置电路设计,并重点解析了DDR3内存子系统以及PCIe与光纤接口等高速电路的原理图与PCB设计要点,旨在帮助工程师构建稳定可靠的高性能硬件平台。

python9snake的博客 512

Antlr4入门(二)基本概念解析

在上一章中(Antlr4入门(一)IDEA中Antlr的安装与使用),我们安装了Antlr,并编写运行了第一个程序“Hello world”。而在本章中,我们将学习语言类应用程序相关的重要过程、术语和数据结构。 一. 术语 语言(language)是由一系列有意义的语句组成,语句(sentence)由词组组成,词组(phrase)是由更小的子词组(subphrase)和词汇符号(vocabulary symbols)组成。 举个例子,英语就是一种语言,“Keep on going never gi.

qq_37771475的博客 5208

LockSupport源码解析

一、前言     LockSupport 和 CAS 是Java并发包中很多并发工具控制机制的基础,它们底层其实都是依赖Unsafe实现。     LockSupport是用来创建锁和其他同步类的基本线程阻塞原语。LockSupport 提供park()和unpark()方法实现阻塞 线程和解除线程阻塞,LockSup...

weixin_42146366的博客 569

【C# + HALCON 机器视觉】HALCON经典算子:光流法运动分析(optical_flow_mg)

摘要:本文面向智能监控人流统计需求,研究C#与HALCON集成开发中optical_flow_mg算子的应用。通过RTSP获取视频流,利用光流法计算运动矢量,结合形态学操作与区域筛选实现行人区域分割,最终完成人流量统计与热力图可视化。详细阐述ROI局部处理等性能优化策略、try-catch异常捕获机制及跨平台集成方案。实验表明,该系统检测准确率达93.6%,单帧处理时间42ms,为公共场所人流量统计提供了完整可行的技术方案。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 1441

LockSupport 深入源码解析

  LockSupport是一个线程工具类,所有的方法都是静态方法,可以在线程任意位置阻塞、唤醒线程。LockSupport的功能是依赖Unsafe类实现的。   演示示例: package com.securitit.serialize.locks; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport; public class LockSupportTester { public

键盘上流淌的日子 7820

全志平台camera驱动开发(4)NVP6134芯片4路模拟视频BT656输入

前言 1. 调试平台: 全志V5/T7等有BT656或BT1120的并行接口,理论有DVP接口的一般都支持 2. NVP6134可使用多路视频同时输入 硬件连接 模拟camera1 模拟camera2 NVP6134 ------>NVCSI0 ...

jzwjzw19900922的博客 3532

[Godot][入门] 安装与版本选择:3.x 还是 4.x?(按项目类型一键决策)

摘要: Godot引擎版本选择需根据项目需求权衡3.x与4.x。Godot4.x(如4.2)适合3D开发和新项目,支持Vulkan和GDScript2.0,但生态尚不成熟;Godot3.x(如3.5.3)则更适合稳定2D开发、Web导出及依赖现有插件/教程的场景。安装方式极简,官网下载解压即可运行。新手建议:短期高效选3.x,长期探索选4.x,旧项目勿盲目迁移。附版本对比表及决策树,助开发者快速匹配需求。

技术小甜甜:传播可落地技术,帮助个人和企业降低解决真实场景问题的成本 910

LockSupport 深度解析

AQS 是 JUC 中大多数同步器(SemaphoreFutureTask等)的基础框架。AQS 内部维护了一个虚拟的 CLH (Craig, Landin, and Hagersten) 双向队列来管理等待获取同步状态(如锁)的线程。在 AQS 中的作用:阻塞获取失败的线程: 当一个线程尝试获取同步状态失败时(例如,调用lock()但锁已被占用),AQS 会将该线程包装成一个节点(Node)加入到等待队列的尾部。然后,在将节点安全地插入队列后,AQS 会调用(这里的this。

左灯右行的爱情 1360

动画实例化:千人同屏不卡顿的秘密

是一种将大量相同骨骼结构的角色动画批量处理、批量渲染的技术。动画计算与渲染解耦,动画数据在CPU或GPU上批量计算,渲染时通过GPU Instancing一次性绘制大量角色。极大减少DrawCall,提升大规模角色(如MMO、RTS、群体AI等)动画的运行效率。动画Bake:编辑器下将所有动画片段Bake为骨骼矩阵纹理。实例参数管理:每个角色维护自己的动画状态、帧索引等。批量渲染:用DrawMeshInstancedIndirect等API批量渲染,Shader中采样骨骼数据。剔除与LOD。

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 419

JDK源码解析之LockSupport

前言:     之前关于AQS和ReentrantLock的介绍中,在获取锁和释放锁的操作中,有一个类被反复使用到,就是LockSupport.java     在AQS.lock()方法中,调用到了LockSupport.park(Object blocker)方法     在AQS.unlock()方法中,调用到了LockSupport.unpark(Thread thread)方法 ...

恐龙弟旺仔的博客 718

【RT-DETR有效改进】计算训练好权重文件对应的FPS、推理每张图片的平均时间(科研必备)

本文给大家带来的改进机制是利用我们训练好的权重文件计算FPS,同时打印每张图片所利用的平均时间,模型大小(以MB为单位),同时支持batch_size功能的选择,对于轻量化模型的读者来说,本文的内容对你一定有帮助,可以清晰帮你展示出模型速度性能的提升以及轻量化的效果(模型大小),对于以提高精度为目的的读者本文也能够帮助大家展示出现阶段的模型速度指标。所以本文的内容是十分有用的机制,对于大家发表论文来说,下面的图片为运行后的效果可以看到,该有的指标均已打印(本文内容为我独家创新,全网无第二份)下面是效果图和文

Snu77的博客 3628

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

LockSupport 类解析

java LockSupport 类解析。方法介绍。适用场景。与 Synchronized 的比较。

一步一步往上爬 1168

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

9.LockSupport源码解析

package com.xz.concurrent.locks; /** * 类简介:用来阻塞当前线程和唤醒指定被阻塞的线程 park() unpark(Thread thread)实现的 * 实现:调用unpark(thread) , 会将线程的许可permit设置为1, * 调用park()方法时,若将当前线程的permit是1.将permit的值设置为0,并立即返回,若当前线程的pe...

x18829525953的博客 150

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Java中LockSupport源码深度解析

是Java并发包中一个基于Unsafe类实现的线程阻塞和唤醒工具类。通过源码分析,我们了解了其数据结构、核心方法以及性能特点。在实际开发中,合理使用可以提升程序的并发性能和灵活性。希望这篇文章能帮助您更好地理解的源码实现!如果您有更多问题,欢迎随时提问。

u011403205的博客 458

LockSupport(park&unpark)源码解析

LockSupport(park/unpark)源码解析 park方法 park() public static void park() { UNSAFE.park(false, 0L); } park(Object blocker) public static void park(Object blocker) { Thread t = Thread.currentThread(); setBlocker(t, blocker); UNSAFE.park(false, 0

我的博客 1331

Java 线程同步基础类 LockSupport 解析

LockSupport 类提供了基本的线程同步原语,是实现 AbstractQueuedSynchronizer 和 ReentrantLock 的基础。

albon arith 1149

​LockSupport源码解析

JUC包中进行线程阻塞和线程唤醒的时候使用了一个工具类,这个类就是LockSupport,在AQS中对线程的阻塞和唤醒就是依靠此类完成的,那么LockSupport是如何实现的里?确实当...

tianjingle 113

Java LockSupport以及park、unpark方法源码深度解析

介绍了JUC中的LockSupport阻塞工具以及park、unpark方法的底层原理,从Java层面深入至JVM层面。

终生学习践行者 5765

【JUC】2、LockSupport 解析与面试题(一)

LockSupport 解析1、带着面试题学习2、介绍2.1、LockSupport类简介2.2、LockSupport使用场景2.3、LockSupport使用示例3、源码解析3.1 类属性3.2 类方法3.2.1 方法总览3.3 重点方法代码展开3.3.1 park3.3.2 unpark4、扩展4.1 UNSAFE.PARK 和 UNSAFE.UNPARK4.2 Thread.sleep、Object.wait、LockSupport.park 区别4.2.1 使用wait阻塞线程4.2.2 使用pa

真正的大师永远怀着一颗学徒的心 848

jdk1.8 LockSupport源码解析

/* * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * Written by Doug Lea with assistance from ...

lc 328
上一篇: 带你三分钟了解OWASP TOP 10 2017 RC2
下一篇: ES单机搭建
kenty w
博客等级 码龄9年 29粉丝 13原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值