LockSupport使用

LockSupport使用

一、简介

LockSupport是线程同步工具,定义了一组静态方法控制控制线程的阻塞和同步。

二、分析

2.1 源码

LockSupport源码不长,方法及其用法请看源码注释,源码如下:

package java.util.concurrent.locks;
import sun.misc.Unsafe;
public class LockSupport {
    //唤醒指定线程
    //如果指定线程阻塞则唤醒
    //如果指定线程没阻塞则下次阻塞时直接唤醒
    //上述唤醒操作只针对已经启动的线程有效
    public static void unpark(Thread thread) {
        if (thread != null)
            UNSAFE.unpark(thread);
    }

    //阻塞当前线程,blocker代表阻塞对象(阻塞线程的同步对象),用于问题排查(使用类型jstack等工具可查看阻塞对象),通常传当前线程this
    public static void park(Object blocker) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        UNSAFE.park(false, 0L);
        setBlocker(t, null);
    }

    //限时阻塞当前线程,阻塞时间不超过指定纳秒,参数blocker为阻塞对象
    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);
        }
    }

    //限时阻塞当前线程,阻塞时间直到指定时间(绝对时间,自1970年开始的毫秒数)为止,参数blocker为阻塞对象
    //the absolute time, in milliseconds from the Epoch
    public static void parkUntil(Object blocker, long deadline) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        UNSAFE.park(true, deadline);
        setBlocker(t, null);
    }

    //返回指定线程的阻塞对象,如果线程没阻塞,则返回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);
    }

    //限时阻塞当前线程,阻塞时间直到指定时间(绝对时间,自1970年开始的毫秒数)为止
    //the absolute time, in milliseconds from the Epoch
    public static void parkUntil(long deadline) {
        UNSAFE.park(true, deadline);
    }
}

2.2 实现

LockSupport核心方法是park和unpark,即是阻塞和唤醒,其实现是采用置标志位,值只有0和1:

  • LockSupport.park: 标志位置0;
  • LockSupport.unpark: 标志位置1;

注意:

  1. LockSupport.unpark唤醒操作,同一时刻,多次置标志位,若中间时刻未使用,则标识为仍为1;
  2. 置标志位只有线程启动后能生效;

三、使用示例

package LockSupportSt;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

public class LockSupportPaper {
    public static void main(String[] args) throws Exception {
        Thread t1 = new TestThread();
        t1.start();

        TimeUnit.SECONDS.sleep(1);
        //唤醒线程
        LockSupport.unpark(t1);
        System.out.println("unpark t1");
    }

    static class TestThread extends Thread {
        @Override
        public void run() {
            System.out.println("thread start");
            //阻塞,同时指定阻塞对象,即当前线程
            LockSupport.park(this);
//            LockSupport.parkNanos(1000*1000*1000);  //限时阻塞
            System.out.println("thread end");
        }
    }
}

备注:
注释唤醒代码,使用jstack打印阻塞时堆栈的部分片段如下:


"Thread-0" #13 prio=5 os_prio=31 tid=0x00007fd80d833800 nid=0x5803 waiting on condition [0x000070000e756000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x000000076ae33fd8> (a LockSupportSt.LockSupportPaper$TestThread)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at LockSupportSt.LockSupportPaper$TestThread.run(LockSupportPaper.java:21)

发布了274 篇原创文章 · 获赞 95 · 访问量 50万+

猜你喜欢

转载自blog.csdn.net/chinabestchina/article/details/105354624