LockSupport源码解析

14 篇文章 0 订阅
7 篇文章 0 订阅

今天和朋友讨论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.
 * 提供了创建锁信息的原生方法
 *
 * <p>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 <em>may</em> 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有一些
 * 有别于锁的特性,具体特性如下。
 *
 * <p>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时间的浪费
 *
 * <p>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用于记录当前线程在哪个对象上阻塞了,这样的记录可以方便的进行线程阻塞原因的
 * 诊断和分析。
 *
 * <p>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:
 * 该类也可以用于实现更加上层的锁工具,而且她自身也是一个非常有用的并发控制程序。
 * 
 * 下面是推荐是用方式:
 *
 *  <pre> {@code
 * while (!canProceed()) { ... LockSupport.park(this); }}</pre>
 *
 * 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.
 *
 * <p><b>Sample Usage.</b> Here is a sketch of a first-in-first-out
 * non-reentrant lock class:
 *  <pre> {@code
 * class FIFOMutex {
 *   private final AtomicBoolean locked = new AtomicBoolean(false);
 *   private final Queue<Thread> waiters
 *     = new ConcurrentLinkedQueue<Thread>();
 *
 *   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());
 *   }
 * }}</pre>
 */

2、源码解读

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值