18.3.4 ReentrantLock与synchronized区别
1. 基础概念对比
1.1 ReentrantLock简介
public class ReentrantLockBasics {
private final ReentrantLock lock = new ReentrantLock();
private int counter = 0;
// ReentrantLock基本用法
public void increment() {
lock.lock(); // 获取锁
try {
counter++;
System.out.println("Counter: " + counter + ", Thread: " + Thread.currentThread().getName());
} finally {
lock.unlock(); // 释放锁(必须在finally中)
}
}
// 尝试获取锁
public boolean tryIncrement() {
if (lock.tryLock()) { // 尝试获取锁,不阻塞
try {
counter++;
return true;
} finally {
lock.unlock();
}
}
return false;
}
// 超时获取锁
public boolean incrementWithTimeout(long timeout, TimeUnit unit) {
try {
if (lock.tryLock(timeout, unit)) { // 带超时的尝试获取锁
try {
counter++;
return true;
} finally {
lock.unlock();
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return false;
}
public int getCounter() {
return counter;
}
}
1.2 synchronized基本用法回顾
public class SynchronizedBasics {
private int counter = 0;
// synchronized方法
public synchronized void increment() {
counter++;
System.out.println("Counter: " + counter + ", Thread: " + Thread.currentThread().getName());
}
// synchronized代码块
public void incrementBlock() {
synchronized (this) {
counter++;
}
}
// 静态synchronized方法
public static synchronized void staticMethod() {
System.out.println("静态同步方法");
}
public int getCounter() {
synchronized (this) {
return counter;
}
}
}
2. 核心区别对比
2.1 功能特性对比
锁的实现 |
API层面的互斥锁 |
JVM层面的内置锁 |
可重入性 |
支持 |
支持 |
公平性 |
支持公平锁和非公平锁 |
非公平锁 |
中断响应 |
支持中断 |
不支持中断 |
超时机制 |
支持超时获取锁 |
不支持 |
条件变量 |
支持多个Condition |
只有一个wait/notify |
锁状态查询 |
可查询锁状态 |
无法查询 |
性能 |
高并发下性能更好 |
JVM优化后性能接近 |
2.2 详细功能对比演示
public class FeatureComparison {
private final ReentrantLock reentrantLock = new ReentrantLock(true); // 公平锁
private final Object synchronizedLock = new Object();
// 1. 公平性对比
public void demonstrateFairness() {
System.out.println("=== 公平性对比演示 ===");
// ReentrantLock公平锁
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
final int threadId = i;
executor.submit(() -> {
for (int j = 0; j < 3; j++) {
reentrantLock.lock();
try {
System.out.println("公平锁 - 线程" + threadId + "获得锁,执行第" + (j + 1) + "次");
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
reentrantLock.unlock();
}
}
});
}
executor.shutdown();
try {
executor.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// synchronized(非公平)
ExecutorService executor2 = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
final int threadId = i;
executor2.submit(() -> {
for (int j = 0; j < 3; j++) {
synchronized (synchronizedLock) {
System.out.println("synchronized - 线程" + threadId + "获得锁,执行第" + (j + 1) + "次");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
});
}
executor2.shutdown();
}
// 2. 中断响应对比
public void demonstrateInterruptibility() {
System.out.println("=== 中断响应对比演示 ===");
// ReentrantLock支持中断
Thread lockThread = new Thread(() -> {
try {
System.out.println("ReentrantLock线程尝试获取锁...");
reentrantLock.lockInterruptibly(); // 可中断的锁获取
try {
System.out.println("ReentrantLock线程获得锁");
Thread.sleep(5000);
} finally {
reentrantLock.unlock();
}
} catch (InterruptedException e) {
System.out.println("ReentrantLock线程被中断");
}
});
Thread interruptThread = new Thread(() -> {
try {
Thread.sleep(1000);
System.out.println("中断ReentrantLock线程");
lockThread.interrupt();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
lockThread.start();
interruptThread.start();
try {
lockThread.join();
interruptThread.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// synchronized不支持中断(演示)
Thread syncThread = new Thread(() -> {
synchronized (synchronizedLock) {
System.out.println("synchronized线程获得锁,开始长时间操作");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println("synchronized线程被中断,但仍持有锁");
}
}
});
syncThread.start();
}
// 3. 超时机制对比
public void demonstrateTimeout() {
System.out.println("=== 超时机制对比演示 ===");
// ReentrantLock支持超时
Thread holderThread = new Thread(() -> {
reentrantLock.lock();
try {
System.out.println("持有锁的线程开始长时间操作");
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
reentrantLock.unlock();
}
});
Thread timeoutThread = new Thread(() -> {
try {
System.out.println("尝试在2秒内获取锁...");
if (reentrantLock.tryLock(2, TimeUnit.SECONDS)) {
try {
System.out.println("成功获取锁");
} finally {
reentrantLock.unlock();
}
} else {
System.out.println("获取锁超时");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
holderThread.start();
try {
Thread.sleep(1000); // 确保holderThread先获取锁
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
timeoutThread.start();
}
}
3. 条件变量对比
3.1 ReentrantLock的Condition
public class ConditionExample {
private final ReentrantLock lock = new ReentrantLock();
private final Condition notEmpty = lock.newCondition();
private final Condition notFull = lock.newCondition();
private final Queue<Integer> queue = new LinkedList<>();
private final int capacity = 5;
// 生产者
public void produce(int item) throws InterruptedException {
lock.lock();
try {
while (queue.size() == capacity) {
System.out.println("队列已满,生产者等待");
notFull.await(); // 等待队列不满
}
queue.offer(item);
System.out.println("生产: " + item + ", 队列大小: " + queue.size());
notEmpty.signal(); // 通知消费者队列不空
} finally {
lock.unlock();
}
}
// 消费者
public int consume() throws InterruptedException {
lock.lock();
try {
while (queue.isEmpty()) {
System.out.println("队列为空,消费者等待");
notEmpty.await(); // 等待队列不空
}
int item = queue.poll();
System.out.println("消费: " + item + ", 队列大小: " + queue.size());
notFull.signal(); // 通知生产者队列不满
return item;
} finally {
lock.unlock();
}
}
public void demonstrateCondition() {
// 创建生产者线程
Thread producer = new Thread(() -> {
try {
for (int i = 1; i <= 10; i++) {
produce(i);
Thread.sleep(200);
}
} catch (InterruptedExcepti
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
Java面试圣经 文章被收录于专栏
Java面试圣经,带你练透java圣经
查看11道真题和解析