Java 的 java.util.concurrent.locks 源码分析

包含接口和类


java.util.concurrent.locks 包下包含如下接口和类
image.png
jdk 截图如下:
image.png

为什么使用 Lock,Lock 和 synchronized 的区别

类别 synchronized Lock
存在层次 Java 的关键字,在 jvm 层面上 是一个类
锁的释放 1、以获取锁的线程执行完同步代码,释放锁 2、线程执行发生异常,jvm 会让线程释放锁 在 finally 中必须释放锁,不然容易造成线程死锁
锁的获取 假设 A 线程获得锁,B 线程等待。如果 A 线程阻塞,B 线程会一直等待 分情况而定,Lock 有多个锁获取的方式,具体下面会说道,大致就是可以尝试获得锁,线程可以不用一直等待
锁状态 无法判断 可以判断
锁类型 可重入 不可中断 非公平 可重入 可判断 可公平(两者皆可)
性能 少量同步 大量同步

Lock 接口

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

public interface Lock {
    //获取锁
    void lock();
    //获得锁除非当前线程被中断
    void lockInterruptibly() throws InterruptedException;
    //当在调用时刻时锁有效,则获得锁
    boolean tryLock();
    //在指定时间内获得锁,并且在该时间内线程没有被中断
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
    //释放锁
    void unlock();
    //返回该锁实例的一个Condition,用于线程同步
    Condition newCondition();
}

Condition 接口

任一个 Java 对象,都拥有一组监视器方法(定义在 java.lang.Object 类上),主要包括 wait()、wait(long)、notify()、notifyAll() 方法,这些方法与 synchronized 关键字配合,可以实现等待 / 通知模式。Condition 接口也提供了类似 Object 的监视器方法,与 Lock 配合可以实现等待 / 通知模式,但两者的使用方式以功能特性有一定的区别。Object 的监视器方法与 Condition 接口对比如下:

对比项 Object 监视器方法 Condition
前置条件 获取对象的监视器锁 调用 Lock.lock()获取锁,调用 Lock.newCondition() 获取 Condition 对象
调用方法 直接调用 如:object.wait() 直接调用 如:condition.await()
等待队列个数 一个 多个
当前线程释放锁并进入等待队列 支持 支持
当前线程释放锁并进入等待队列,在等待状态中不响应中断 不支持 支持
当前线程释放锁并进入超时等待状态 支持 支持
当前线程释放锁并进入等待状态到将来的某个时间 不支持 支持
唤醒等待队列中的一个线程 支持 支持
唤醒等待队列中的全部线程 支持 支持

源码


package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;
import java.util.Date;

/**
 * 使用方法
 * class BoundedBuffer {
 *   final Lock lock = new ReentrantLock();
 *   final Condition notFull  = lock.newCondition(); 
 *   final Condition notEmpty = lock.newCondition(); 
 *
 *   final Object[] items = new Object[100];
 *   int putptr, takeptr, count;
 *
 *   public void put(Object x) throws InterruptedException {
 *     lock.lock();
 *     try {
 *       while (count == items.length)
 *         notFull.await();
 *       items[putptr] = x;
 *       if (++putptr == items.length) putptr = 0;
 *       ++count;
 *       notEmpty.signal();
 *     } finally {
 *       lock.unlock();
 *     }
 *   }
 *
 *   public Object take() throws InterruptedException {
 *     lock.lock();
 *     try {
 *       while (count == 0)
 *         notEmpty.await();
 *       Object x = items[takeptr];
 *       if (++takeptr == items.length) takeptr = 0;
 *       --count;
 *       notFull.signal();
 *       return x;
 *     } finally {
 *       lock.unlock();
 *     }
 *   }
 * }
 * 
 *
 * condition调用await方法后,condition的锁是释放了的,condition调用signal或者signalAll后,再重新获得锁
 *
 */
public interface Condition {

    //当前线程进入等待状态直到被通知(signal)或中断。
    void await() throws InterruptedException;
    //当前线程进入等待状态直到被通知,该方法不响应中断。
    void awaitUninterruptibly();
    //当前线程进入等待状态直到被通知、中断或者超时,返回值表示剩余超时时间。
    long awaitNanos(long nanosTimeout) throws InterruptedException;
    //当前线程进入等待状态直到被通知、中断或者到某个时间。如果没有到指定时间就被通知,方法返回true,否则,表示到了指定时间,返回false。
    boolean awaitUntil(Date deadline) throws InterruptedException;
    //唤醒一个等待在Condition上的线程,该线程从等待方法返回前必须获得与Condition相关联的锁。
    void signal()
    //唤醒所有等待在Condition上的线程,能够从等待方法返回的线程必须获得与Condition相关联的锁。
    void signalAll();
}

  
    展开阅读全文