locks 接口
public interface Lock {
void lock(); //获取锁
void lockInterruptibly() throws InterruptedException; // 中断等待获取锁的线程
boolean tryLock(); //尝试获取锁,如果成功返回true
//尝试获取锁,在等待时间内,成功返回 true。支持打断
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock(); //释放锁
Condition newCondition();
}
reentrantlock
定义
reentrantLock 是独占锁,与synchronized 相同,并且也两者也同为 重入锁。
reentrantLock 可以相应 中断在获取锁时候。
reentrantLock 可以定义公平锁(默认为非公平),可以定义获取锁的等待时长。
专业术语的含义
重入锁: 当前线程获取 锁成功后,里面如果还需要获取这个锁,那么会立刻获取得到。
例子:
public class ReentrantLockTest {
public static void main(String[] args) throws InterruptedException {
ReentrantLock lock = new ReentrantLock();
for (int i = 1; i <= 3; i++) {
lock.lock();
}
for(int i=1;i<=3;i++){
try {
} finally {
lock.unlock();
}
}
}
}
上面的代码通过lock()
方法先获取锁三次,然后通过unlock()
方法释放锁3次,程序可以正常退出。从上面的例子可以看出,ReentrantLock是可以重入的锁,当一个线程获取锁时,还可以接着重复获取多次。在加上ReentrantLock的的独占性,我们可以得出以下ReentrantLock和synchronized的相同点。
- 1.ReentrantLock和synchronized都是独占锁,只允许线程互斥的访问临界区。但是实现上两者不同:synchronized加锁解锁的过程是隐式的,用户不用手动操作,优点是操作简单,但显得不够灵活。一般并发场景使用synchronized的就够了;ReentrantLock需要手动加锁和解锁,且解锁的操作尽量要放在finally代码块中,保证线程正确释放锁。ReentrantLock操作较为复杂,但是因为可以手动控制加锁和解锁过程,在复杂的并发场景中能派上用场。
- 2.ReentrantLock和synchronized都是可重入的。synchronized因为可重入因此可以放在被递归执行的方法上,且不用担心线程最后能否正确释放锁;而ReentrantLock在重入时要却确保重复获取锁的次数必须和重复释放锁的次数一样,否则可能导致其他线程无法获得该锁。
公平锁与非公平锁:
公平锁是指当锁可用时,在锁上等待时间最长的线程将获得锁的使用权。而非公平锁则随机分配这种使用权。和synchronized一样,默认的ReentrantLock实现是非公平锁,因为相比公平锁,非公平锁性能更好。当然公平锁能防止饥饿,某些情况下也很有用。在创建ReentrantLock的时候通过传进参数true
创建公平锁,如果传入的是false
或没传参数则创建的是非公平锁
ReentrantLock lock = new ReentrantLock(true);
实现
浅层代码,之后的实现暂时不看。先了解特性吧。
/**
* Creates an instance of {@code ReentrantLock} with the
* given fairness policy.
*
* @param fair {@code true} if this lock should use a fair ordering policy
*/
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
用法
package com.zxy.lock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
/**
* 公平锁与非公平锁
*
* @author : wb-zxy450245
* @date : 2020/6/17
*/
public class FairLockTest {
//公平锁 or 非公平 new ReentrantLock(true|false);
private static ReentrantLock reentrantLock = new ReentrantLock(false);
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
new Thread(new LockDemo(i)).start();
}
}
static class LockDemo implements Runnable {
private int id = 0;
public LockDemo(int id) {
this.id = id;
}
@Override
public void run() {
try {
//为了说明问题,在每个线程获取锁前都睡 10毫秒。
TimeUnit.MILLISECONDS.sleep(10L);
} catch (InterruptedException e) {
}
for (int i = 0; i < 2; i++) {
reentrantLock.lock();
System.out.println("当前线程_" + id + "_for_" + i);
reentrantLock.unlock();
}
}
}
}
参考地址:https://www.cnblogs.com/takumicx/p/9338983.html
公平锁是指当锁可用时,在锁上等待时间最长的线程将获得锁的使用权。而非公平锁则随机分配这种使用权。和synchronized一样,默认的ReentrantLock实现是非公平锁,因为相比公平锁,非公平锁性能更好。当然公平锁能防止饥饿,某些情况下也很有用。在创建ReentrantLock的时候通过传进参数true
创建公平锁,如果传入的是false
或没传参数则创建的是非公平锁、
//创建公平锁 - (默认参数是否false ,非公平锁)
ReentrantLock lock = new ReentrantLock(true);
源码是:
/**
* Creates an instance of {@code ReentrantLock} with the
* given fairness policy.
*
* @param fair {@code true} if this lock should use a fair ordering policy
*/
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
ReentrantLock可响应中断
参考:https://www.cnblogs.com/takumicx/p/9338983.html
3.2节
ReentrantReadWriteLock
ReentrantReadWriteLock可重入读写锁
使用参考地址:https://www.cnblogs.com/china2k/p/8013086.html
实现原理:https://www.toutiao.com/i6768421906807783949/?in_ogs=1&from=singlemessage&traffic_source=CS1114&utm_source=HW&source=search_tab&utm_medium=wap_search&prevent_activate=1&original_source=1&in_tfs=HW&channel=
读写锁:
AQS:https://www.yuque.com/haolonglong/msvmro/hspkh1