浅析LockSupport实现原理

微信公众号:MyClass社区
若有问题或建议,请公众号留言java

LockSupport介绍

     在阅读开源项目的的时候,常常看到有人使用LockSupport,咱们今天来看一下它的使用和基本原理。首先,简单的介绍一下LockSupport,它是并发包中的一个线程阻塞工具类,LockSupport提供park()和unpark()两个方法实现阻塞线程和解除线程阻塞。下面看看它与wait和notify使用上有何区别?微信

LockSupport的使用

     咱们知道Object类也能够实现阻塞和唤醒,wait和notify只能在同步代码块或者同步方法中调用,这里是为了保证多线程object操做wait和notify的原子性。多线程

public void waitAndNotify() throws Exception {
    final Object obj = new Object();
    Thread testThread = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("do task");
            System.out.println("wait---");
            synchronized (obj){
                try {
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("continue do task");
        }
    });
    testThread.start();
    //这里sleep是为了保证已经阻塞
    Thread.sleep(1000);
    synchronized (obj){
        System.out.println("notify--------");
        obj.notify();
    }
}
并发

      下面是LockSupport的使用,LockSupport.park()阻塞线程,而后调用unpark进行唤醒,不须要像wait/notify那样先要保证进入wait,才能唤醒线程,不然会无限等待。LockSupport若是先调用unpark后,线程再调用park是不会被一直阻塞的,使用起来更加简单灵活。jvm

public void lockSupportTest({
    final Object obj = new Object();
    Thread testThread = new Thread(new Runnable() {
        @Override
        public void run(
{
            System.out.println("do task");
            System.out.println("wait---");
            LockSupport.park();
            System.out.println("continue do task");
        }
    });
    testThread.start();
    //这里sleep是为了保证park成功
    Thread.sleep(1000);
    System.out.println("notify--------");
    LockSupport.unpark(testThread);
}
ide

以上的执行效果:函数

do task
wait---
notify--------
continue do task
工具

1.LockSupport不须要在同步代码块里 。因此线程间也不须要维护一个共享的同步对象了,实现了线程间的解耦。
2.notify和notifyAll,通常的若是多个线程都对同一个对象进行阻塞,notify()是不肯定唤醒哪个线程的等待。
3.unpark函数能够先于park调用,因此不须要担忧线程间的执行的前后顺序。
4.wait/notify和notifyAll和LockSupport阻塞的线程是相互隔离的,object阻塞的是对象维度,不一样的线程能够对同一个对象进行操做,而LockSupport是线程维度的阻塞,因此不会交叉影响,你们能够本身试一试。spa

LockSupport实现原理

wait方法实现

      首先说一下wait,它是在同步机制中的一个操做,须要放弃同步对象锁的monitor,monitor信息保存在对象头信息中,以前讲过synchronized锁信息也是保存在对象头信息(Mark Word)中,当线程调用wait的时候,将线程放入该对象锁ObjectMonitor的等待唤醒集合wait-set中来实现将线程挂起。.net

notify方法实现

      lock.notify()方法底层也是经过ObjectMonitor的void notify()实现,获取对象的信息的WaitSet列表中的第一个节点。这里须要注意的是,在jdk的notify方法注释是随机唤醒一个线程,实际上是第一个ObjectWaiter节点

LockSuppor实现

/**
 * 若是给定线程的许可尚不可用,则使其可用。
 * 若是线程调用了park,调用unpark将解除其阻塞状态。
 * 若是没有park,保证下一次调用 park也不会受阻塞。
 * 启动了线程,调用才会有效果,否哦无效。
 * @param thread: 要执行 unpark 操做的线程;该参数为 null 表示此操做没有任何效果。
 */

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

/**
 * 为了线程调度,在许可可用以前阻塞当前线程。
 * 若是许可可用,则使用该许可,而且该调用当即返回;
 * 不然,为线程调度禁用当前线程,并在发生如下三种状况之一之前,使其处于休眠状态:
 *  1. 其余某个线程将当前线程做为目标调用 unpark
 *  2. 其余某个线程中断当前线程
 *  3. 该调用不合逻辑地(即毫无理由地)返回
 */

public static void park({
    UNSAFE.park(false0L);
}

LockSuppor的park/unpark方法实际上是操做Unsafe类里的函数。

//参数线程
public native void unpark(Thread jthread);
//isAbsolute参数是指明时间是绝对的,仍是相对的。
public native void park(boolean isAbsolute, long time);

      经过openjdk的源码看看其native实现,HotSpot里park/unpark的实现,每一个java线程都有一个Parker实例,Parker类是这样定义的,在Parker类里的_counter字段,就是用来记录线程是否阻塞状态的,网上不少人称之为所谓的“许可”状态,具体逻辑就不扩展了,有机会能够深刻了解一下底层jvm的实现原理。

class Parker : public os::PlatformParker {
private:
  volatile int _counter ;
  ...
public:
  void park(bool isAbsolute, jlong time);
  void unpark();
  ...
}
class PlatformParker : public CHeapObj<mtInternal> {
  protected:
    pthread_mutex_t _mutex [1] ;
    pthread_cond_t  _cond  [1] ;
    ...

总结

  1. LockSuppor真正解耦了线程之间的同步,线程之间再也不须要一个Object或者其它变量来存储状态;

  2. 当调用park时,先尝试直接可否拿到“许可”,即_counter>0时,若是成功,则把_counter设置为0,并返回;

  3. 当unpark时,直接设置_counter为1,而且返回。若是_counter以前的值是0,则还要唤醒在park中等待的线程;

  4. 简单的理解就是维护_counter的变量,当park时,这个变量置为了0,表明当前线程阻塞了,等待许可,当unpark时,这个变量置为1,则线程获取许可表明唤醒继续执行;

  5. 屡次调用unpark方法和调用一次unpark方法效果同样,由于都是直接将_counter赋值为1,而不是加1。

本文分享自微信公众号 - MyClass社区(MyClass_ZZ)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索