Loading

LockSupport使用

1.简介

在JDK1.6中的java.util.concurrent的子包locks中引了LockSupport这个API,LockSupport是一个比较底层的工具类,用来创建锁和其他同步工具类的基本线程阻塞原语。java锁和同步器框架的核心 AQS: AbstractQueuedSynchronizer,就是通过调用 LockSupport .park()和 LockSupport .unpark()的方法,来实现线程的阻塞和唤醒的。

2.使用

  • 示例1

    public class TestLockSupport {
     public static void main(String[] args) {
         //使用lombda表达式创建一个线程t
         Thread t = new Thread(() -> {
             for (int i = 0; i < 10; i++) {
                 System.out.println(i);
                 if (i == 5) {
                     //使用LockSupport的park()方法阻塞当前线程t
                     LockSupport.park();
                 }
                 try {
                     //使当前线程t休眠1秒
                     TimeUnit.SECONDS.sleep(1);
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
             }
         });
         //启动当前线程t
         t.start();
         //唤醒线程t,这行代码实际运行过程中会比上面的park()方法先执行,但是线程t没有被阻塞,由此可以看出LockSupport的unpark()方法可以先于LockSupport的park()方法执行
         LockSupport.unpark(t);
     }
    }
    
  • 示例2

    public class TestLockSupport {
     public static void main(String[] args) {
         //使用lombda表达式创建一个线程t
         Thread t = new Thread(() -> {
             for (int i = 0; i < 10; i++) {
                 System.out.println(i);
                 if (i == 5) {
                     //调用LockSupport的park()方法阻塞当前线程t
                     LockSupport.park();
                 }
                 if (i == 8) {
                     //调用LockSupport的park()方法阻塞当前线程t,虽然在主线程中调用了unpark方法,但是由于在i==5的时候调用过park方法,此时这里还是会阻塞
                     LockSupport.park();
                 }
    
                 try {
                     //使当前线程t休眠1秒
                     TimeUnit.SECONDS.sleep(1);
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
             }
         });
         //启动当前线程t
         t.start();
         //唤醒线程t
         LockSupport.unpark(t);
     }
    }
    
  • 总结

    1.LockSupport不需要synchornized加锁就可以实现线程的阻塞和唤醒

    2.LockSupport.unpartk()可以先于LockSupport.park()执行,并且线程不会阻塞

    3.如果一个线程处于等待状态,连续调用了两次park()方法,就会使该线程永远无法被唤醒

3.底层实现

park()和unpark()方法的实现是由Unsefa类提供的,而Unsefa类是由C和C++语言完成的,其实原理也是比较好理解的,它主要通过一个变量作为一个标识,变量值在0,1之间来回切换,当这个变量大于0的时候线程就获得了“令牌”,从这一点我们不难知道,其实park()和unpark()方法就是在改变这个变量的值,来达到线程的阻塞和唤醒的。

posted @ 2022-01-24 23:43  ZT丶  阅读(72)  评论(0编辑  收藏  举报