包含接口和类
java.util.concurrent.locks 包下包含如下接口和类
jdk 截图如下:
为什么使用 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();
}