LockSupport源码解析

今天和朋友讨论Java中的锁机制的时候,谈论到了LockSupport类,在之前一直没有使用过该类,所以当提到该类的时候还是有点陌生,然后看了一下JDK的源码和该类相关的技术博客,整理了一下该类的原理和使用场景。

使用

package mthread;

import org.junit.Test;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

/**
 * 锁测试
 * Start at: 2018/3/25 22:29
 *
 * @author muhong
 */
public class LockSupportTest {

    /** 等待满足的条件 */
    private volatile boolean finish = false;

    @Test
    public void test(){

        Thread waiter = new Thread(()->{
            long currentSeconds = TimeUnit.SECONDS.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS);
            System.out.println(currentSeconds+":线程执行开始....并等待结束通知");
            while (!finish){ // 由于park方法会被中断返回,所以需要重复检查“条件”
                LockSupport.park(this);
            }
            currentSeconds = TimeUnit.SECONDS.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS);
            System.out.println(currentSeconds+":线程执行结束");
        });
        waiter.start();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long currentSeconds = TimeUnit.SECONDS.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS);
        System.out.println(currentSeconds+":通知线程结束等待");
        finish = true;
        LockSupport.unpark(waiter);
    }
}

源码解析

1、首先看看java doc描述

/**
 * Basic thread blocking primitives for creating locks and other
 * synchronization classes.
 * 提供了创建锁信息的原生方法
 *
 * 

This class associates, with each thread that uses it, a permit * (in the sense of the {@link java.util.concurrent.Semaphore * Semaphore} class). A call to {@code park} will return immediately * if the permit is available, consuming it in the process; otherwise * it may block. A call to {@code unpark} makes the permit * available, if it was not already available. (Unlike with Semaphores * though, permits do not accumulate. There is at most one.) * 每一个线程都用于可以使用该类,当线程使用该类的时候,会生成一个permit(类似一个和信 * 号量相关作用的数据结构)和该线程关联,通过该permit完成锁相关的工作,该permit有一些 * 有别于锁的特性,具体特性如下。 * *

Methods {@code park} and {@code unpark} provide efficient * means of blocking and unblocking threads that do not encounter the * problems that cause the deprecated methods {@code Thread.suspend} * and {@code Thread.resume} to be unusable for such purposes: Races * between one thread invoking {@code park} and another thread trying * to {@code unpark} it will preserve liveness, due to the * permit. Additionally, {@code park} will return if the caller's * thread was interrupted, and timeout versions are supported. The * {@code park} method may also return at any other time, for "no * reason", so in general must be invoked within a loop that rechecks * conditions upon return. In this sense {@code park} serves as an * optimization of a "busy wait" that does not waste as much time * spinning, but must be paired with an {@code unpark} to be * effective. * 该permit的特性是不会产生线程suspend和resume两种状态,即使在一个线程调用park * 另外一个线程调用unpark的时候也会保持线程的活性。而且如果调用park方法的线程在阻塞 * 过程中被中断,那么park方法将立刻无条件返回,所以总得来说,在调用park方法的时候需要 * 循环检测通过LockSupport方法共享的资源是否满足条件,如果不满足条件那么需要继续park * 一直等待到共享资源满足为止。从某种意义上来说,park方法其实是自旋锁的一种优化,避免了 * 忙等引起的CPU时间的浪费 * *

The three forms of {@code park} each also support a * {@code blocker} object parameter. This object is recorded while * the thread is blocked to permit monitoring and diagnostic tools to * identify the reasons that threads are blocked. (Such tools may * access blockers using method {@link #getBlocker(Thread)}.) * The use of these forms rather than the original forms without this * parameter is strongly encouraged. The normal argument to supply as * a {@code blocker} within a lock implementation is {@code this}. * blocker用于记录当前线程在哪个对象上阻塞了,这样的记录可以方便的进行线程阻塞原因的 * 诊断和分析。 * *

These methods are designed to be used as tools for creating * higher-level synchronization utilities, and are not in themselves * useful for most concurrency control applications. The {@code park} * method is designed for use only in constructions of the form: * 该类也可以用于实现更加上层的锁工具,而且她自身也是一个非常有用的并发控制程序。 * * 下面是推荐是用方式: * *

 {@code
 * while (!canProceed()) { ... LockSupport.park(this); }}
* * where neither {@code canProceed} nor any other actions prior to the * call to {@code park} entail locking or blocking. Because only one * permit is associated with each thread, any intermediary uses of * {@code park} could interfere with its intended effects. * *

Sample Usage. Here is a sketch of a first-in-first-out * non-reentrant lock class: *

 {@code
 * class FIFOMutex {
 *   private final AtomicBoolean locked = new AtomicBoolean(false);
 *   private final Queue waiters
 *     = new ConcurrentLinkedQueue();
 *
 *   public void lock() {
 *     boolean wasInterrupted = false;
 *     Thread current = Thread.currentThread();
 *     waiters.add(current);
 *
 *     // Block while not first in queue or cannot acquire lock
 *     // 循环检查共享资源条件是否满足(因为park返回并不代表共享资源满足条件)
 *     while (waiters.peek() != current ||
 *            !locked.compareAndSet(false, true)) {
 *       LockSupport.park(this);
 *       if (Thread.interrupted()) // ignore interrupts while waiting
 *         wasInterrupted = true;
 *     }
 *
 *     waiters.remove();
 *     if (wasInterrupted)          // reassert interrupt status on exit
 *       current.interrupt();
 *   }
 *
 *   public void unlock() {
 *     locked.set(false);
 *     LockSupport.unpark(waiters.peek());
 *   }
 * }}
*/

2、源码解读

在上面的java doc中已经对整个机制进行了详细的分析,而且该类的大部分功能逻辑依赖于jvm中的unsafe函数,所以就不再进行具体的分析了。

你可能感兴趣的:(java,jdk,源码)