Java多线程系列(五)—LockSupport源码分析

来源:互联网 发布:c语言猜数游戏 编辑:程序博客网 时间:2024/05/18 09:51

Java多线程系列(五)—LockSupport源码分析

LockSupport类是实现锁机制和其他同步类的基础,提供了基本线程阻塞和恢复的原语;

LockSupport中的park() 和 unpark() 的作用分别是阻塞线程和解除阻塞线程,而且park()和unpark()不会遇到“Thread.suspend 和 Thread.resume所可能引发的死锁”问题

个人主页:tuzhenyu’s page
原文地址:Java多线程系列(五)—LockSupport源码分析

(1) LockSupport类的属性

  • 在类加载时进行初始化,主要包括Unsafe类实例和各个字段在Thread类中的内存偏移量;
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();    //获取Unsafe实例        Class<?> tk = Thread.class;        parkBlockerOffset = UNSAFE.objectFieldOffset            (tk.getDeclaredField("parkBlocker"));        //获取类属性parkBlocker在Thread类中的偏移量;        SEED = UNSAFE.objectFieldOffset            (tk.getDeclaredField("threadLocalRandomSeed"));        //获取类属性Seed在Thread类中的偏移量;        PROBE = UNSAFE.objectFieldOffset            (tk.getDeclaredField("threadLocalRandomProbe"));        SECONDARY = UNSAFE.objectFieldOffset            (tk.getDeclaredField("threadLocalRandomSecondarySeed"));        //获取类属性Secondary在Thread类中的偏移量;    } catch (Exception ex) { throw new Error(ex); }}

(2) LockSupport类的方法

  • LockSupport类的构造方法是私有构造方法,因此不能被实例化只能调用其类方法和类属性
private LockSupport() {}     // Cannot be instantiated.
  • LockSupport类的核心方法都是基于Unsafe类的park()和unpark()方法实现的

    • park(boolean isAbsolute,long time)如果isAbsolute为true则为绝对时间,如果为false则为相对时间;如果time为0则表示等待时间无限长直到获取许可;
public native void park(boolean isAbsolute, long time);public native void unpark(Thread thread);
  • 线程处于park()阻塞状态下三种方法解除线程阻塞

    • 时间超时

    • 线程中断

    • unpark()方法解除阻塞

1.LockSupport类的park方法

  • LockSupport类主要有两种park()方法的重载类
public static void park();    //不进行blocker绑定public static void park(Object blocker);    // 将当前线程绑定到blocker
  • park()方法底层实现是通过调用Unsafe类的park(boolean isAbsolute,long time)方法

    • 等待时间time为相对时间的0,线程阻塞直到获取许可
public static void park() {    UNSAFE.park(false, 0L);}
  • park(Object blocker)方法底层是通过setBlocker()方法将线程与blocker绑定

    • 与blocker绑定的park()方法默认是线程阻塞直到获取许可;

    • setBlocker()方法是通过调用Unsafe类的putObject()方法;

public static void park(Object blocker) {    Thread t = Thread.currentThread();    setBlocker(t, blocker);    UNSAFE.park(false, 0L);    setBlocker(t, null);}
  • parkNanos(Object blocker,long nanos)方法是绑定blocker和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);    }}
  • parkUntil(Object blocker,long deadline)是绑定blocker和deadline绝对超时时间
public static void parkUntil(Object blocker, long deadline) {    Thread t = Thread.currentThread();    setBlocker(t, blocker);    UNSAFE.park(true, deadline);    setBlocker(t, null);}

2.LockSupport类的unpark方法

  • unpark()方法执行有两个作用

    • 如果线程处于阻塞状态即线程许可不可用,则unpark()方法使其许可可用,解除阻塞阻塞状态

    • 线程许可可用,保证下一次调用 park 不会受阻塞

public static void unpark(Thread thread) {    if (thread != null)        UNSAFE.unpark(thread);}

(3) LockSupport类的使用

  • 通过LockSupport类实现线程的阻塞和唤醒
class MyThread extends Thread {    private Object object;    public MyThread(Object object) {        this.object = object;    }    public void run() {        System.out.println("before unpark");        try {            Thread.sleep(3000);        } catch (InterruptedException e) {            e.printStackTrace();        }        // 获取blocker        System.out.println("Blocker info " + LockSupport.getBlocker((Thread) object));        // 释放许可        LockSupport.unpark((Thread) object);        // 再次获取blocker        System.out.println("Blocker info " + LockSupport.getBlocker((Thread) object));        System.out.println("after unpark");    }}public class ParkAndUnparkDemo {    public static void main(String[] args) {        MyThread myThread = new MyThread(Thread.currentThread());        myThread.start();        System.out.println("before park");        // 获取许可        LockSupport.park("ParkAndUnparkDemo");        System.out.println("after park");    }}

结论

ParkSupport类是锁机制和同步类的实现基础,其底层是通过调用Unsafe类的park()相关方法实现线程的阻塞和释放;