LockSupport的使用
创始人
2024-02-26 17:25:31
0

参考链接:
LockSupport使用场景及原理详解
AQS的引入

LockSupport的使用

LockSupport是一个工具类,提供了基本的线程阻塞和唤醒功能,它是创建锁和其他同步组件的基础工具,内部是使用sun.misc.Unsafe类实现的。LockSupport和使用它的线程都会关联一个许可,park方法表示消耗一个许可,调用park方法时,如果许可可用则park方法返回,如果没有许可则一直阻塞直到许可可用。unpark方法表示增加一个许可,多次调用并不会积累许可,因为许可数最大值为1。

其次,注意:某个线程可以先被unpark(这时,该线程就获得了一个许可),然后这个线程调用LockSupport.park()时,此时,发现有许可可用,则使用此许可而不会阻塞。

关于LockSupport的补充

LockSupport会为每个线程设置一个permit值,也就是许可。1代表许可可用,0代表许可不可用。permit的最大值是1,最小值是0,当调用park()方法时,如果permit为1,则减为0,继续执行。如果permit已经为0,则阻塞。同理,unpark()方法会消耗一个许可,如果permit的值为0,则增加为1,代表发放许可,如果permit的值已经为1,则不在增加,也就是多次方法许可,并不会累加。当然这里所讲的permit在LockSupport的代码当中没有体现,需要到HotSpot的源码当中查看,以下为截图供查看:

1、/share/vm/runtime/park.hpp中许可的定义字段_counter
在这里插入图片描述

2、park()的实现(部分截图)
在这里插入图片描述

3、unpark()实现
在这里插入图片描述

示例:让3个线程按顺序打印ABC

package com.zzhua;import java.util.concurrent.locks.LockSupport;public class TestABC {private void printA(Thread thread) {System.out.println("A");LockSupport.unpark(thread);}private void printB(Thread thread) {LockSupport.park();System.out.println("B");LockSupport.unpark(thread);}private void printC() {LockSupport.park();System.out.println("C");}public static void main(String[] args) {/* 无论下面哪个线程先被执行,当B和C未获得它们的许可时,都会被阻塞掉,一直到获得许可。或者,它们在它们执行顺先前面的线程执行完后,先给了它们许可后,它们再在park时,再消费此许可这样就可以保证它们的打印顺序LockSupport的存在目的就是为了替换掉jdk自带的wait-notify等待唤醒机制(它只能结合synchronized使用,并且只能唤醒一个或全部唤醒,不够灵活) */TestABC testABC = new TestABC();Thread tC = new Thread(() -> {testABC.printC();});Thread tB = new Thread(() -> {testABC.printB(tC);});Thread tA = new Thread(() -> {testABC.printA(tB);});tC.start();tB.start();tA.start();}}

可正常响应中断

LockSupport.park()方法可以阻塞当前线程,阻塞的过程中,是可以正常响应中断的(如下面例子)。而jdk自带的synchornized当处于阻塞时,是不会响应中断的。

package com.zzhua;import java.util.concurrent.locks.LockSupport;public class TestPark {public static void main(String[] args) {Thread mainThread = Thread.currentThread();new Thread(() -> {try {Thread.sleep(3000L);mainThread.interrupt();} catch (InterruptedException e) {e.printStackTrace();}}).start();LockSupport.park();System.out.println("main....");// 3s后,正常输出main....// 说明park()方法可正常响应中断}}

jdk自带的synchronized在阻塞期间是不会响应中断的,以下示例,在10s后,正常输出main…


package com.zzhua;public class TestPark {public static void main(String[] args) throws InterruptedException {Thread mainThread = Thread.currentThread();new Thread(() -> {try {Thread.sleep(3000L);mainThread.interrupt();System.out.println("尝试中断main线程...(但是main线程没反应)");} catch (InterruptedException e) {e.printStackTrace();}}).start();new Thread(() -> {try {synchronized (TestPark.class) {Thread.sleep(10000L);}} catch (InterruptedException e) {e.printStackTrace();}}).start();Thread.sleep(50L);System.out.println("要进入synchronized了");synchronized (TestPark.class) {System.out.println("main....");}}}

相关内容

热门资讯

俄大使:俄罗斯不再将伯尔尼视为... 【俄罗斯驻瑞士大使谢尔盖·加尔莫宁向卫星通讯社表示,瑞士完全采取亲乌克兰的立场,俄罗斯不再将伯尔尼视...
男子当街拦车砸玻璃,一女童站在... 12月20日,湖北大冶市网民发视频称,一名男子在新冶大道附近当街拦车砸玻璃,期间车外有女童哭喊。 ...
知名短剧女演员承认对助理动手:... 近日,知名短剧女演员被曝和助理发生肢体冲突,双方冲突录音曝光。两人疑因工资结算起争执。 12月21日...
5915万元索赔落空!德龙汇能... 深圳商报·读创客户端记者 穆砚 12月19日晚间,德龙汇能集团股份有限公司(以下简称“德龙汇能”或“...
怎样找到高效刑事律师,赵可律师... 影响刑事律师效率的因素在寻找高效刑事律师时,需考虑多方面因素。 专业经验是关键,经验丰富的律师见过各...
《藏在故宫里的法律印迹》讲座在... 讲座现场 日前,复旦大学法学院优秀校友、故宫博物院研究馆员张剑虹研究员以“藏在故宫里的法律印迹”为题...
9天举报92次违停仍“原地不动... 成都市民小多,因为骑共享单车下班屡屡被违停车辆逼到机动车道,一怒之下在网上发布“宣言”:开展为期30...
谷歌起诉爬虫公司SerpApi... IT之家 12 月 21 日消息,据科技媒体 The Verge 昨天报道,谷歌已对爬虫工具开发商 ...