目录
在多线程编程中,锁是保证线程安全的核心机制。本文将从基础到高级,全面解析Java中的各种锁机制。
引言: 为什么需要锁?
在多线程环境中,多个线程可能同时方位你共享资源,如果不加以控制,就会导致数据不一致,脏读等问题。锁机制正是为了解决这些问题而存在的,它通过互斥访问来保证临界区代码的线程安全。
一、基础锁机制:synchronized
synchronized是Java中最基础、最常用的锁机制,由JVM底层实现。
1.1 三种使用方式
// 1. 同步实例方法- 锁对象是当前实例
public synchronized void instanceMethod(){
//临时区代码
}
//2. 同步静态方法 - 锁对象是当前类的Class对象
public static synchronized void staticMethod(){
//临时区代码
}
// 3. 同步代码块 - 手动指定锁对象
public void method() {
Object lock = new Object();
synchronized(lock) {
// 临界区代码
}
}
1.2 synchronized的特性
| 特性 | 说明 |
|---|---|
| 可重入性 | 同一线程可重复获取同意把锁 |
| 非公平锁 | 不保证线程获取锁的顺序 |
| 自动释放 | 代码块结束或异常时自动释放锁 |
| 内存语义 | 保证可见性和有序性(遵循happens-before原则) |
1.3 synchronized的局限性
- 无法中断: 等待锁的线程不能中断
- 无法超时: 不能设置获取锁的超时时间
- 单一条件: 只有一个等待队列(notify随机唤醒)
二、ReenttrantLock: 功能更强大的锁
ReentrantLock是java.util.concurrent.locks包下的显示锁,需要手动获取和释放。
2.1 基本用法
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockDemo{
private final ReentrantLock lock = new ReentrantLock();
public void doSometing(){
lock.lock(); //获取锁
try{
//临界区代码
} finally{
lock.unlock();//必须在finally中释放。
}
}
}
2.2 ReentrantLock的核心优势
1)可中断获取锁
public void tryLockInterruptibly() thows InterruptedException{
try{
lock.lockInterruptibly();// 可被中断的获取锁方式
//临界区代码
} finally{
if(lock.isHeldByCurrentThread()){
lock.unlock();
}
}
}
2) 尝试获取锁(支持超时)
public boolean tryDoSomething(long timeout, TimeUnit unit){
try{
if(lock.tryLock(timeout,unit)){
//尝试获取锁,支持超时
try{
//临界区代码
return true;
} finally{
lock.unlock();
}
}
return false;
} catch (InterruptedException e){
Thread.currentThread().interrupt();
}
}
3) 公平锁与非公平锁
// 公平锁 - 按照请求顺序获取锁
ReentrantLock fairLock = new ReentrantLock(true);
// 非公平锁 - 默认方式,性能更高
ReentrantLock unfairLock = new ReentrantLock(false);
4) 多条件变量
class BoundedBuffer {
private final ReentrantLock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition(); // 条件:不满
private final Condition notEmpty = lock.newCondition()

最低0.47元/天 解锁文章
1093

被折叠的 条评论
为什么被折叠?



