1.reentrantlock介绍
reentrantlock 是java 并发包(java.util.concurrent.locks)中提供的一个可重入互斥锁,功能类似于synchronized关键字,但提供了更灵活的锁控制机制。
2.reentrantlock核心特性
2.1可重入性
同一个线程可以多次获取同一把锁,而不会产生死锁
reentrantlock lock = new reentrantlock();
public void func1() {
lock.lock();
try {
inner();
} finally {
lock.unlock();
}
}
public void func2() {
lock.lock(); // 同一个线程可以再次获取锁
try {
// 操作
} finally {
lock.unlock();
}
}2.2公平性选择
支持公平锁和非公平锁两种模式
默认使用非公平锁,非公平锁和公平锁的区别在于公平锁多了判断在等待队列中是否已经有线程在排队的条件。
- 非公平锁:默认,吞吐量高
- 公平锁:按等待时间分配,避免饥饿
// 非公平锁 reentrantlock unfairlock = new reentrantlock(); // 公平锁 reentrantlock fairlock = new reentrantlock(true);
2.3中断响应
支持在等待锁的过程中响应中断
使用lock.lockinterruptibly()即可设置可中断的获取锁
public void method() throws interruptedexception {
lock.lockinterruptibly(); // 可中断的获取锁
try {
// 操作
} finally {
lock.unlock();
}
}2.4超时机制
- trylock():立即返回是否获取成功
- trylock(long timeout, timeunit unit):带超时的尝试
3.reentrantlock基本使用方法
我们来模拟一个简单的多线程环境下对单一共享变量做更改的场景
public class counter {
private final reentrantlock lock = new reentrantlock();
private int count = 0;
public void increment() {
lock.lock(); // 获取锁
try {
count++;
} finally {
lock.unlock(); // 必须放在finally中确保释放
}
}
}和sychronized类似,其本质都是将需保证线程安全的变量放到代码块中,使用锁将代码块包裹。不一样的点在于reentrantlock需要手动释放锁,为了保证每次使用锁后安全地释放,我们使用finally关键字去实现锁的释放。
4.reentrantlock和sychronized对比
synchronized和reentrantlock都是java 中提供的可重入锁,但却有着较多的不同点
| reentrantlock | synchronized | |
| 实现方式 | java代码实现 | jvm内置(c/c++) |
| 锁获取方式 | 手动 lock()/unlock() | 自动获取/释放 |
| 可中断性 | lockinterruptibly() | 不支持 |
| 超时机制 | trylock() | 不支持 |
| 公平锁 | 支持 | 不支持 |
| 性能优化 | aqs+cas | 锁升级 |
虽说在性能上二者相差无几,但是reentrantlock提供了更多可选的功能,灵活性要比传统synchronized锁要更高,所以在大部分场景中,我们会选择使用reentrantlock作为第一选择,而synchronized因为其有着自动获取和释放锁的优势,在简单的业务场景中会经常看见它的身影。
5.reentrantlock使用主要事项
5.1锁的释放
由于reentrantlock没有提供自动获取和释放锁,所以在每次使用完后必须手动释放
lock.lock();
try {
// 临界区代码
} finally {
lock.unlock();
}5.2锁的层级嵌套
虽然reentrantlock支持可重入锁,但是随着嵌套层级增加,代码可读性会大大下降
//嵌套层次过深
public void methoda() {
lock.lock();
try {
methodb();
} finally {
lock.unlock();
}
}
public void methodb() {
lock.lock(); // 再次获取
try {
// ...
} finally {
lock.unlock();
}
}以上就是java reentrantlock的可重入性与公平锁机制详解的详细内容,更多关于java reentrantlock的资料请关注代码网其它相关文章!
发表评论