简单看看LockSupport和AQS

这次我们可以看看并发中锁的原理,大概会说到AQS,ReentrantLock,ReentrantReadWriteLock以及JDK8中新增的StampedLock,这些都是在java并发中很重要的东西,慢慢看吧!

 

一.LockSupport工具类

  LockSupport工具类是jdk中rt.jar里面的,主要作用是挂起和唤醒线程,该类是创建锁和创建其他同步类的基础。还有我们要知道,LockSupport这个类是以Unsafe这个类为基础,讲过前面简单的看了看Unsafe,是不是觉得还是比较熟悉的吧!

  我们先看看LockSupport的park(英文翻译:停下,坐下)和unpark(英文翻译:唤醒,启动)方法,注意,这两个方法和wait和notify功能很像,但是在这里我更喜欢叫做授权

  简单的看一个例子:

package com.example.demo.study;
import java.util.concurrent.locks.LockSupport;

public class Study0130 {

    public static void main(String[] args) {
        System.out.println("main begin");                
        LockSupport.park();       
        System.out.println("main end");
    }
}

 

  我们可以看到我们直接调用park方法的话,当前的线程就阻塞了,不能到后面去了,这里我们可以说当前线程没有被LockSupport类授权,没有许可证,所以到这里碰到park()这个路口就只能挂了;那么怎么样才能使得当前线程被授权呢?我们就需要unpark()方法进行授权

package com.example.demo.study;
import java.util.concurrent.locks.LockSupport;

public class Study0130 {

    public static void main(String[] args) {
        //这里就是给当前线程授权了,当前线程可以随便跑,碰到park都不会挂
        LockSupport.unpark(Thread.currentThread());
        
        System.out.println("main begin");
        LockSupport.park();
        System.out.println("main end");

    }
}

简单看看LockSupport和AQS_第1张图片

 

  还记得以前的wait和notify的用法么?一个线程A中调用了wait方法,那么线程A就挂起了,如果在线程B中调用notify方法,那么A线程就会被唤醒;这里的park和unpark方法也可以实现这种,看以下代码:

package com.example.demo.study;

import java.util.concurrent.locks.LockSupport;

public class Study0130 {

    public static void main(String[] args) {

        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("thread1 start");
                //线程1会阻塞
                LockSupport.park();
                System.out.println("thread1 end");
            }
        });

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("thread2 start");
                //给线程1授权
                LockSupport.unpark(thread1);
                System.out.println("thread2 end");
            }
        });
        thread1.start();
        thread2.start();
    }
}

简单看看LockSupport和AQS_第2张图片

 

  我们打开LockSupport的park和unpark方法可以发现,就是调用的Unsafe实现的,可惜看不到源码...

简单看看LockSupport和AQS_第3张图片

 

  假如我们调用park方法使得线程阻塞太久了也不是我们想看到的,我们还可以使用parkNanos设置阻塞时间,当时间到了,就会自动返回:

简单看看LockSupport和AQS_第4张图片

 

  最后说一下,还可以调用park方法的时候传进去一个对象,比如LockSupport.park(this);这样使用可以使用jstack pid命令查看堆栈信息的时候,可以看到是那个类被阻塞了!

简单看看LockSupport和AQS_第5张图片

   到此为止,应该就是LockSupport的常用方法了!

你可能感兴趣的:(简单看看LockSupport和AQS)