Lock重入锁
前言
在并发编程中有两个核心问题, 一个是互斥另一个是同步。在java sdk并发包中,lock就是解决互斥问题,conditon就是解决同步问题。
Lock
lock有三个重要的特性:
- 能够响应中断: 线程在没有获取锁的时候,进入阻塞状态。我们能够给进入阻塞状态的线程发送信号,重新唤醒它。
- 支持超时: 在无法获取锁的时候,就等待一定的时间。超时就自动返回。
- 非阻塞的获取锁:如果无法获取锁就马上返回。
以下为它的API
// 支持中断的 API
void lockInterruptibly()
throws InterruptedException;
// 支持超时的 API
boolean tryLock(long time, TimeUnit unit)
throws InterruptedException;
// 支持非阻塞获取锁的 API
boolean tryLock();
lock–内存可见性问题
可以先看代码
class X {
private final Lock rtl =
new ReentrantLock();
int value;
public void addOne() {
// 获取锁
rtl.lock();
try {
value+=1;
} finally {
// 保证锁能释放
rtl.unlock();
}
}
}
这段代码,如果T1线程将value改为1 那么t2线程在执行的时候能够看见吗?
答案是肯定的。
它是利用了volatile相关的happes-before规则。java sdk里面的ReentrantLock,内部持有一个volatile的成员变量state,获取锁的时候,会读写 state的值;解锁的时候,也会读写state,在执行value+=1之后,又读写了一次volatile变量state。根据相关的Happens-before规则:
- 顺序性执行: 对于线程T1, value+=1 Happens-before释放锁的操作unlock()。
- volatile变量规则: 由于state= 1 会先读取state,所以线程T1的unlock() 操作Happens-before()线程T2的lock()操作。
- 传递性规则:线程T1的value+=1 Happens-Before线程T2的lock()操作。
class SampleLock {
volatile int state;
// 加锁
lock() {
// 省略代码无数
state = 1;
}
// 解锁
unlock() {
// 省略代码无数
state = 0;
}
}
lock—重入锁
ReentrantLock,指的是线程可以重复获取同一把锁。例如下面的代码,当线程T1执行到1处时,已经获取到了锁rtl,当在1处调用get()方法时,会在2处再次对锁rtl执行加锁操作。如果锁rtl是可重入的,那么线程T1可以再次加锁成功。如果锁rtl是不可重入的,那么线程T1此时会被阻塞。
class X {
private final Lock rtl =
new ReentrantLock();
int value;
public int get() {
// 获取锁
rtl.lock(); ②
try {
return value;
} finally {
// 保证锁能释放
rtl.unlock();
}
}
public void addOne() {
// 获取锁
rtl.lock();
try {
value = 1 + get(); ①
} finally {
// 保证锁能释放
rtl.unlock();
}
}
}
LOCK公平锁与非公平锁
ReentrantLock有两个构造方法。一个是无参构造,一个是传入fair。fair参数代表的是锁的公平策略,如果传入 true就表示需要构造一个公平锁,反之则表示构造一个非公平锁。
// 无参构造函数:默认非公平锁
public ReentrantLock() {
sync = new NonfairSync();
}
// 根据公平策略参数创建锁
public ReentrantLock(boolean fair){
sync = fair ? new FairSync()
: new NonfairSync();
}
公平锁就是先等待先唤醒,非公平锁是随机唤醒。
锁的使用经验
- 永远只在更新对象的成员变量时加锁
- 永远只在访问可变的成员变量
- 永远不在调用其他对象的方法时加锁
这三条中最后一条主要是担心在调用慢方法,如长时间IO或者业务复杂。 也会担心其他方法里面本身有锁,在调用的时候加锁会出现双重锁, 容易导致死锁。
如果您觉得文章对您有帮助,请您在下面写一点留言,点一个赞。 谢谢!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~