AQS理解之一,基础知识——LockSupport

AQS理解之一,基础知识——LockSupport

LockSupport类位于java.util.concurrent包下。

顾名思义,就是一个实现锁的辅助类。

来看下他的类结构:

AQS理解之一,基础知识——LockSupport_第1张图片

其中的变量都是通过UNSAFE类来赋值,代码如下:

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();
            Class tk = Thread.class;
            parkBlockerOffset = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("parkBlocker"));
            SEED = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomSeed"));
            PROBE = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomProbe"));
            SECONDARY = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomSecondarySeed"));
        } catch (Exception ex) { throw new Error(ex); }
    }

parkBlockerOffset 是Thread类中的parkBlocker参数,其他参数类似。

parkBlockerOffset参数设置之后可以在jstack的时候对给这个变量设置了值的线程进行观察。

方法是park()和unpark(Thread t)和这两个方法的一些带时间参数方法。

通过看这个类的注释,可以知道park 和unpark实际上是对线程的阻塞与解除阻塞。

park: 阻塞线程,线程在一下三种情况下会被打开:

1.调用unpark方法,释放该线程的许可。

2.该线程被中断。

3.时间到期。

LockSupport的park和unpark操作的实际动作。

1.调用unpark

如果没有可用线程,则给定许可(permit就变成1(不会累计))

如果有线程被阻塞,解除锁,同时park返回。

如果给定线程没有启动,则该操作不能保证有任何效果.

2.调用park,则会检测permit是否为1。

如果为1则将permit变成0;

如果不为1,则堵塞线程,直到permit变为1.

我们知道wait和notify也可以实现对线程的阻塞和解除,他们的区别主要在于:

1,unpark会直接指定要解除阻塞的线程,而notify需要知道有一个确定的线程在wait,如果有多个线程在阻塞,则不能确定知道哪个会被解除阻塞。

2,wait和notify有先后顺序,即必须先wait,再notify才能解除,而park和unpark则没有,可以先给权限,再阻塞,阻塞会直接返回。

3,wait时线程如果被interrupt,会报错InterruptedException,而park时则会正常结束。

4,wait/notify面向对象,而LockSupport面向线程

你可能感兴趣的:(源码学习,多线程,AQS)