java锁实现原理
哪吒 2023/6/15
# Java锁实现原理
# 1. 锁的基础概念
# 1.1 什么是锁
锁是一种同步机制,用于控制多个线程对共享资源的访问。在Java中,锁确保在任意时刻只有一个线程能够访问被保护的代码段或资源。
public class LockBasicDemo {
private int count = 0;
private final Object lock = new Object();
// 使用synchronized关键字加锁
public synchronized void incrementSync() {
count++;
}
// 使用synchronized代码块
public void incrementBlock() {
synchronized (lock) {
count++;
}
}
public static void main(String[] args) throws InterruptedException {
LockBasicDemo demo = new LockBasicDemo();
// 创建多个线程并发访问
Thread[] threads = new Thread[10];
for (int i = 0; i < 10; i++) {
threads[i] = new Thread(() -> {
for (int j = 0; j < 1000; j++) {
demo.incrementSync();
}
});
threads[i].start();
}
// 等待所有线程完成
for (Thread thread : threads) {
thread.join();
}
System.out.println("Final count: " + demo.count);
}
}
# 3. ReentrantLock实现原理
# 3.1 ReentrantLock基本使用
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;
public class ReentrantLockDemo {
private final ReentrantLock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
private int count = 0;
private boolean ready = false;
// 基本的加锁解锁
public void increment() {
lock.lock();
try {
count++;
System.out.println(Thread.currentThread().getName() + ": " + count);
} finally {
lock.unlock();
}
}
// 可重入性演示
public void reentrantDemo() {
lock.lock();
try {
System.out.println("First lock acquired");
nestedLock();
} finally {
lock.unlock();
}
}
private void nestedLock() {
lock.lock(); // 同一线程再次获取锁
try {
System.out.println("Nested lock acquired");
} finally {
lock.unlock();
}
}
// 条件变量使用
public void producer() {
lock.lock();
try {
while (!ready) {
System.out.println("Producer waiting...");
condition.await();
}
System.out.println("Producer working...");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.unlock();
}
}
public void consumer() {
lock.lock();
try {
ready = true;
System.out.println("Consumer ready, signaling producer");
condition.signal();
} finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
ReentrantLockDemo demo = new ReentrantLockDemo();
// 测试基本功能
Thread[] threads = new Thread[3];
for (int i = 0; i < 3; i++) {
threads[i] = new Thread(() -> {
for (int j = 0; j < 3; j++) {
demo.increment();
}
}, "Thread-" + i);
threads[i].start();
}
for (Thread thread : threads) {
thread.join();
}
// 测试可重入性
System.out.println("\n=== 可重入性测试 ===");
demo.reentrantDemo();
// 测试条件变量
System.out.println("\n=== 条件变量测试 ===");
Thread producer = new Thread(demo::producer, "Producer");
Thread consumer = new Thread(demo::consumer, "Consumer");
producer.start();
Thread.sleep(1000); // 确保producer先启动
consumer.start();
producer.join();
consumer.join();
}
}
# 3.2 公平锁与非公平锁
import java.util.concurrent.locks.ReentrantLock;
public class FairLockDemo {
private final ReentrantLock fairLock = new ReentrantLock(true); // 公平锁
private final ReentrantLock unfairLock = new ReentrantLock(false); // 非公平锁
public void testFairLock() {
System.out.println("=== 公平锁测试 ===");
testLock(fairLock, "Fair");
}
public void testUnfairLock() {
System.out.println("\n=== 非公平锁测试 ===");
testLock(unfairLock, "Unfair");
}
private void testLock(ReentrantLock lock, String type) {
Thread[] threads = new Thread[5];
for (int i = 0; i < 5; i++) {
final int threadId = i;
threads[i] = new Thread(() -> {
for (int j = 0; j < 3; j++) {
lock.lock();
try {
System.out.println(type + " Lock - Thread " + threadId +
" acquired lock, iteration " + j);
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.unlock();
}
}
}, "Thread-" + i);
}
for (Thread thread : threads) {
thread.start();
}
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
public static void main(String[] args) {
FairLockDemo demo = new FairLockDemo();
demo.testFairLock();
demo.testUnfairLock();
}
}
# 3.3 AQS(AbstractQueuedSynchronizer)原理
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
// 自定义同步器示例
public class CustomLock {
private final Sync sync = new Sync();
// 基于AQS的自定义同步器
private static class Sync extends AbstractQueuedSynchronizer {
// 尝试获取锁
@Override
protected boolean tryAcquire(int arg) {
// 使用CAS操作尝试将state从0设置为1
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
// 尝试释放锁
@Override
protected boolean tryRelease(int arg) {
if (getState() == 0) {
throw new IllegalMonitorStateException();
}
setExclusiveOwnerThread(null);
setState(0);
return true;
}
// 是否被当前线程独占
@Override
protected boolean isHeldExclusively() {
return getExclusiveOwnerThread() == Thread.currentThread();
}
}
public void lock() {
sync.acquire(1);
}
public void unlock() {
sync.release(1);
}
public boolean tryLock() {
return sync.tryAcquire(1);
}
public static void main(String[] args) throws InterruptedException {
CustomLock lock = new CustomLock();
int count = 0;
Thread[] threads = new Thread[5];
for (int i = 0; i < 5; i++) {
threads[i] = new Thread(() -> {
for (int j = 0; j < 1000; j++) {
lock.lock();
try {
// count++; // 这里需要使用volatile或其他同步机制
System.out.println(Thread.currentThread().getName() + " working");
} finally {
lock.unlock();
}
}
}, "Thread-" + i);
threads[i].start();
}
for (Thread thread : threads) {
thread.join();
}
}
}
# 4. 读写锁(ReadWriteLock)
# 4.1 ReentrantReadWriteLock使用
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.HashMap;
import java.util.Map;
public class ReadWriteLockDemo {
private final Map<String, String> cache = new HashMap<>();
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
private final ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock();
private final ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock();
// 读操作
public String get(String key) {
readLock.lock();
try {
System.out.println(Thread.currentThread().getName() + " reading: " + key);
Thread.sleep(100); // 模拟读操作耗时
return cache.get(key);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return null;
} finally {
readLock.unlock();
}
}
// 写操作
public void put(String key, String value) {
writeLock.lock();
try {
System.out.println(Thread.currentThread().getName() + " writing: " + key + "=" + value);
Thread.sleep(200); // 模拟写操作耗时
cache.put(key, value);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
writeLock.unlock();
}
}
// 锁降级示例
public String getAndUpdate(String key, String newValue) {
writeLock.lock();
try {
String oldValue = cache.get(key);
cache.put(key, newValue);
// 锁降级:在持有写锁的情况下获取读锁
readLock.lock();
try {
writeLock.unlock(); // 释放写锁
// 现在只持有读锁
System.out.println("Lock downgrade: " + key + " updated from " + oldValue + " to " + newValue);
return oldValue;
} finally {
readLock.unlock();
}
} finally {
// 确保写锁被释放(如果还持有的话)
if (rwLock.isWriteLockedByCurrentThread()) {
writeLock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException {
ReadWriteLockDemo demo = new ReadWriteLockDemo();
// 初始化一些数据
demo.put("key1", "value1");
demo.put("key2", "value2");
// 创建多个读线程
Thread[] readers = new Thread[5];
for (int i = 0; i < 5; i++) {
readers[i] = new Thread(() -> {
for (int j = 0; j < 3; j++) {
String value = demo.get("key1");
System.out.println(Thread.currentThread().getName() + " got: " + value);
}
}, "Reader-" + i);
}
// 创建写线程
Thread writer = new Thread(() -> {
for (int i = 0; i < 3; i++) {
demo.put("key1", "newValue" + i);
}
}, "Writer");
// 启动所有线程
for (Thread reader : readers) {
reader.start();
}
writer.start();
// 等待所有线程完成
for (Thread reader : readers) {
reader.join();
}
writer.join();
// 测试锁降级
System.out.println("\n=== 锁降级测试 ===");
demo.getAndUpdate("key1", "finalValue");
}
}
# 4.2 StampedLock(JDK 8+)
import java.util.concurrent.locks.StampedLock;
public class StampedLockDemo {
private double x, y;
private final StampedLock sl = new StampedLock();
// 写操作
public void write(double newX, double newY) {
long stamp = sl.writeLock();
try {
x = newX;
y = newY;
System.out.println(Thread.currentThread().getName() + " wrote: (" + x + ", " + y + ")");
} finally {
sl.unlockWrite(stamp);
}
}
// 乐观读
public double distanceFromOrigin() {
long stamp = sl.tryOptimisticRead();
double curX = x, curY = y;
if (!sl.validate(stamp)) {
// 乐观读失败,升级为悲观读锁
stamp = sl.readLock();
try {
curX = x;
curY = y;
System.out.println(Thread.currentThread().getName() + " upgraded to read lock");
} finally {
sl.unlockRead(stamp);
}
} else {
System.out.println(Thread.currentThread().getName() + " optimistic read succeeded");
}
return Math.sqrt(curX * curX + curY * curY);
}
// 悲观读
public double distanceFromOriginPessimistic() {
long stamp = sl.readLock();
try {
System.out.println(Thread.currentThread().getName() + " pessimistic read");
return Math.sqrt(x * x + y * y);
} finally {
sl.unlockRead(stamp);
}
}
// 读锁升级为写锁
public void moveIfAtOrigin(double newX, double newY) {
long stamp = sl.readLock();
try {
while (x == 0.0 && y == 0.0) {
// 尝试将读锁升级为写锁
long ws = sl.tryConvertToWriteLock(stamp);
if (ws != 0L) {
// 升级成功
stamp = ws;
x = newX;
y = newY;
System.out.println(Thread.currentThread().getName() + " upgraded to write lock and moved to (" + x + ", " + y + ")");
break;
} else {
// 升级失败,释放读锁,获取写锁
sl.unlockRead(stamp);
stamp = sl.writeLock();
System.out.println(Thread.currentThread().getName() + " acquired write lock directly");
}
}
} finally {
sl.unlock(stamp);
}
}
public static void main(String[] args) throws InterruptedException {
StampedLockDemo demo = new StampedLockDemo();
// 写线程
Thread writer = new Thread(() -> {
for (int i = 0; i < 5; i++) {
demo.write(i, i * 2);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}, "Writer");
// 乐观读线程
Thread optimisticReader = new Thread(() -> {
for (int i = 0; i < 10; i++) {
double distance = demo.distanceFromOrigin();
System.out.println("Distance: " + distance);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}, "OptimisticReader");
// 悲观读线程
Thread pessimisticReader = new Thread(() -> {
for (int i = 0; i < 5; i++) {
double distance = demo.distanceFromOriginPessimistic();
System.out.println("Pessimistic Distance: " + distance);
try {
Thread.sleep(150);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}, "PessimisticReader");
writer.start();
optimisticReader.start();
pessimisticReader.start();
writer.join();
optimisticReader.join();
pessimisticReader.join();
// 测试锁升级
System.out.println("\n=== 锁升级测试 ===");
demo.write(0, 0); // 重置为原点
demo.moveIfAtOrigin(10, 20);
}
}
# 5. 锁的性能比较与分析
# 5.1 不同锁的性能测试
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.StampedLock;
public class LockPerformanceTest {
private static final int THREAD_COUNT = 10;
private static final int ITERATIONS = 100000;
private int synchronizedCounter = 0;
private int reentrantLockCounter = 0;
private int readWriteLockCounter = 0;
private int stampedLockCounter = 0;
private final Object syncLock = new Object();
private final ReentrantLock reentrantLock = new ReentrantLock();
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
private final StampedLock stampedLock = new StampedLock();
// synchronized性能测试
public void testSynchronized() throws InterruptedException {
long startTime = System.currentTimeMillis();
Thread[] threads = new Thread[THREAD_COUNT];
for (int i = 0; i < THREAD_COUNT; i++) {
threads[i] = new Thread(() -> {
for (int j = 0; j < ITERATIONS; j++) {
synchronized (syncLock) {
synchronizedCounter++;
}
}
});
threads[i].start();
}
for (Thread thread : threads) {
thread.join();
}
long endTime = System.currentTimeMillis();
System.out.println("Synchronized: " + (endTime - startTime) + "ms, Counter: " + synchronizedCounter);
}
// ReentrantLock性能测试
public void testReentrantLock() throws InterruptedException {
long startTime = System.currentTimeMillis();
Thread[] threads = new Thread[THREAD_COUNT];
for (int i = 0; i < THREAD_COUNT; i++) {
threads[i] = new Thread(() -> {
for (int j = 0; j < ITERATIONS; j++) {
reentrantLock.lock();
try {
reentrantLockCounter++;
} finally {
reentrantLock.unlock();
}
}
});
threads[i].start();
}
for (Thread thread : threads) {
thread.join();
}
long endTime = System.currentTimeMillis();
System.out.println("ReentrantLock: " + (endTime - startTime) + "ms, Counter: " + reentrantLockCounter);
}
// ReadWriteLock性能测试(写操作)
public void testReadWriteLock() throws InterruptedException {
long startTime = System.currentTimeMillis();
Thread[] threads = new Thread[THREAD_COUNT];
for (int i = 0; i < THREAD_COUNT; i++) {
threads[i] = new Thread(() -> {
for (int j = 0; j < ITERATIONS; j++) {
rwLock.writeLock().lock();
try {
readWriteLockCounter++;
} finally {
rwLock.writeLock().unlock();
}
}
});
threads[i].start();
}
for (Thread thread : threads) {
thread.join();
}
long endTime = System.currentTimeMillis();
System.out.println("ReadWriteLock: " + (endTime - startTime) + "ms, Counter: " + readWriteLockCounter);
}
// StampedLock性能测试
public void testStampedLock() throws InterruptedException {
long startTime = System.currentTimeMillis();
Thread[] threads = new Thread[THREAD_COUNT];
for (int i = 0; i < THREAD_COUNT; i++) {
threads[i] = new Thread(() -> {
for (int j = 0; j < ITERATIONS; j++) {
long stamp = stampedLock.writeLock();
try {
stampedLockCounter++;
} finally {
stampedLock.unlockWrite(stamp);
}
}
});
threads[i].start();
}
for (Thread thread : threads) {
thread.join();
}
long endTime = System.currentTimeMillis();
System.out.println("StampedLock: " + (endTime - startTime) + "ms, Counter: " + stampedLockCounter);
}
public static void main(String[] args) throws InterruptedException {
LockPerformanceTest test = new LockPerformanceTest();
System.out.println("=== 锁性能测试 (" + THREAD_COUNT + " threads, " + ITERATIONS + " iterations each) ===");
test.testSynchronized();
test.testReentrantLock();
test.testReadWriteLock();
test.testStampedLock();
}
}
# 5.2 读写场景性能比较
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.StampedLock;
import java.util.Random;
public class ReadWritePerformanceTest {
private static final int READER_COUNT = 8;
private static final int WRITER_COUNT = 2;
private static final int OPERATIONS = 10000;
private volatile int data = 0;
private final Object syncLock = new Object();
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
private final StampedLock stampedLock = new StampedLock();
private final Random random = new Random();
// synchronized读写测试
public void testSynchronizedReadWrite() throws InterruptedException {
long startTime = System.currentTimeMillis();
Thread[] readers = new Thread[READER_COUNT];
Thread[] writers = new Thread[WRITER_COUNT];
// 创建读线程
for (int i = 0; i < READER_COUNT; i++) {
readers[i] = new Thread(() -> {
for (int j = 0; j < OPERATIONS; j++) {
synchronized (syncLock) {
int value = data; // 读操作
// 模拟读操作耗时
try {
Thread.sleep(0, 1000); // 1微秒
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}, "SyncReader-" + i);
}
// 创建写线程
for (int i = 0; i < WRITER_COUNT; i++) {
writers[i] = new Thread(() -> {
for (int j = 0; j < OPERATIONS; j++) {
synchronized (syncLock) {
data = random.nextInt(1000); // 写操作
// 模拟写操作耗时
try {
Thread.sleep(0, 5000); // 5微秒
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}, "SyncWriter-" + i);
}
// 启动所有线程
for (Thread reader : readers) reader.start();
for (Thread writer : writers) writer.start();
// 等待完成
for (Thread reader : readers) reader.join();
for (Thread writer : writers) writer.join();
long endTime = System.currentTimeMillis();
System.out.println("Synchronized ReadWrite: " + (endTime - startTime) + "ms");
}
// ReadWriteLock读写测试
public void testReadWriteLock() throws InterruptedException {
long startTime = System.currentTimeMillis();
Thread[] readers = new Thread[READER_COUNT];
Thread[] writers = new Thread[WRITER_COUNT];
// 创建读线程
for (int i = 0; i < READER_COUNT; i++) {
readers[i] = new Thread(() -> {
for (int j = 0; j < OPERATIONS; j++) {
rwLock.readLock().lock();
try {
int value = data; // 读操作
// 模拟读操作耗时
Thread.sleep(0, 1000); // 1微秒
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
rwLock.readLock().unlock();
}
}
}, "RWReader-" + i);
}
// 创建写线程
for (int i = 0; i < WRITER_COUNT; i++) {
writers[i] = new Thread(() -> {
for (int j = 0; j < OPERATIONS; j++) {
rwLock.writeLock().lock();
try {
data = random.nextInt(1000); // 写操作
// 模拟写操作耗时
Thread.sleep(0, 5000); // 5微秒
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
rwLock.writeLock().unlock();
}
}
}, "RWWriter-" + i);
}
// 启动所有线程
for (Thread reader : readers) reader.start();
for (Thread writer : writers) writer.start();
// 等待完成
for (Thread reader : readers) reader.join();
for (Thread writer : writers) writer.join();
long endTime = System.currentTimeMillis();
System.out.println("ReadWriteLock: " + (endTime - startTime) + "ms");
}
// StampedLock读写测试
public void testStampedLock() throws InterruptedException {
long startTime = System.currentTimeMillis();
Thread[] readers = new Thread[READER_COUNT];
Thread[] writers = new Thread[WRITER_COUNT];
// 创建读线程(使用乐观读)
for (int i = 0; i < READER_COUNT; i++) {
readers[i] = new Thread(() -> {
for (int j = 0; j < OPERATIONS; j++) {
long stamp = stampedLock.tryOptimisticRead();
int value = data;
if (!stampedLock.validate(stamp)) {
// 乐观读失败,使用悲观读
stamp = stampedLock.readLock();
try {
value = data;
} finally {
stampedLock.unlockRead(stamp);
}
}
// 模拟读操作耗时
try {
Thread.sleep(0, 1000); // 1微秒
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}, "StampedReader-" + i);
}
// 创建写线程
for (int i = 0; i < WRITER_COUNT; i++) {
writers[i] = new Thread(() -> {
for (int j = 0; j < OPERATIONS; j++) {
long stamp = stampedLock.writeLock();
try {
data = random.nextInt(1000); // 写操作
// 模拟写操作耗时
Thread.sleep(0, 5000); // 5微秒
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
stampedLock.unlockWrite(stamp);
}
}
}, "StampedWriter-" + i);
}
// 启动所有线程
for (Thread reader : readers) reader.start();
for (Thread writer : writers) writer.start();
// 等待完成
for (Thread reader : readers) reader.join();
for (Thread writer : writers) writer.join();
long endTime = System.currentTimeMillis();
System.out.println("StampedLock: " + (endTime - startTime) + "ms");
}
public static void main(String[] args) throws InterruptedException {
ReadWritePerformanceTest test = new ReadWritePerformanceTest();
System.out.println("=== 读写场景性能测试 (" + READER_COUNT + " readers, " + WRITER_COUNT + " writers, " + OPERATIONS + " operations each) ===");
test.testSynchronizedReadWrite();
test.testReadWriteLock();
test.testStampedLock();
}
}
# 6. 死锁检测与预防
# 6.1 死锁示例与检测
import java.util.concurrent.locks.ReentrantLock;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.lang.management.ThreadInfo;
public class DeadlockDemo {
private final ReentrantLock lock1 = new ReentrantLock();
private final ReentrantLock lock2 = new ReentrantLock();
// 可能导致死锁的方法1
public void method1() {
lock1.lock();
try {
System.out.println(Thread.currentThread().getName() + " acquired lock1");
Thread.sleep(100);
lock2.lock();
try {
System.out.println(Thread.currentThread().getName() + " acquired lock2");
} finally {
lock2.unlock();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock1.unlock();
}
}
// 可能导致死锁的方法2
public void method2() {
lock2.lock();
try {
System.out.println(Thread.currentThread().getName() + " acquired lock2");
Thread.sleep(100);
lock1.lock();
try {
System.out.println(Thread.currentThread().getName() + " acquired lock1");
} finally {
lock1.unlock();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock2.unlock();
}
}
// 死锁检测
public static void detectDeadlock() {
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
long[] deadlockedThreads = threadBean.findDeadlockedThreads();
if (deadlockedThreads != null) {
ThreadInfo[] threadInfos = threadBean.getThreadInfo(deadlockedThreads);
System.out.println("\n=== 检测到死锁 ===");
for (ThreadInfo threadInfo : threadInfos) {
System.out.println("线程名: " + threadInfo.getThreadName());
System.out.println("线程状态: " + threadInfo.getThreadState());
System.out.println("锁名: " + threadInfo.getLockName());
System.out.println("锁拥有者: " + threadInfo.getLockOwnerName());
System.out.println("---");
}
} else {
System.out.println("未检测到死锁");
}
}
public static void main(String[] args) throws InterruptedException {
DeadlockDemo demo = new DeadlockDemo();
Thread t1 = new Thread(() -> {
demo.method1();
}, "Thread-1");
Thread t2 = new Thread(() -> {
demo.method2();
}, "Thread-2");
// 启动死锁检测线程
Thread detector = new Thread(() -> {
while (true) {
try {
Thread.sleep(1000);
detectDeadlock();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}, "DeadlockDetector");
detector.setDaemon(true);
detector.start();
t1.start();
t2.start();
// 等待一段时间后强制结束
Thread.sleep(5000);
System.out.println("强制结束程序");
System.exit(0);
}
}
# 6.2 死锁预防策略
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.TimeUnit;
import java.util.Random;
public class DeadlockPreventionDemo {
private final ReentrantLock lock1 = new ReentrantLock();
private final ReentrantLock lock2 = new ReentrantLock();
private final Random random = new Random();
// 策略1: 锁排序 - 始终按相同顺序获取锁
public void lockOrderingStrategy() {
// 为锁分配唯一ID,始终按ID顺序获取
ReentrantLock firstLock = System.identityHashCode(lock1) < System.identityHashCode(lock2) ? lock1 : lock2;
ReentrantLock secondLock = System.identityHashCode(lock1) < System.identityHashCode(lock2) ? lock2 : lock1;
firstLock.lock();
try {
System.out.println(Thread.currentThread().getName() + " acquired first lock");
Thread.sleep(100);
secondLock.lock();
try {
System.out.println(Thread.currentThread().getName() + " acquired second lock");
// 执行业务逻辑
} finally {
secondLock.unlock();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
firstLock.unlock();
}
}
// 策略2: 超时机制
public void timeoutStrategy() {
try {
if (lock1.tryLock(1000, TimeUnit.MILLISECONDS)) {
try {
System.out.println(Thread.currentThread().getName() + " acquired lock1");
if (lock2.tryLock(1000, TimeUnit.MILLISECONDS)) {
try {
System.out.println(Thread.currentThread().getName() + " acquired lock2");
// 执行业务逻辑
} finally {
lock2.unlock();
}
} else {
System.out.println(Thread.currentThread().getName() + " failed to acquire lock2, backing off");
}
} finally {
lock1.unlock();
}
} else {
System.out.println(Thread.currentThread().getName() + " failed to acquire lock1, backing off");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
// 策略3: 回退策略
public void backoffStrategy() {
boolean acquired = false;
int attempts = 0;
while (!acquired && attempts < 5) {
try {
if (lock1.tryLock()) {
try {
System.out.println(Thread.currentThread().getName() + " acquired lock1");
if (lock2.tryLock()) {
try {
System.out.println(Thread.currentThread().getName() + " acquired lock2");
// 执行业务逻辑
acquired = true;
} finally {
lock2.unlock();
}
} else {
System.out.println(Thread.currentThread().getName() + " failed to acquire lock2, backing off");
}
} finally {
lock1.unlock();
}
}
if (!acquired) {
attempts++;
// 随机回退时间,避免活锁
Thread.sleep(random.nextInt(100) + 50);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
if (!acquired) {
System.out.println(Thread.currentThread().getName() + " failed to acquire locks after " + attempts + " attempts");
}
}
public static void main(String[] args) throws InterruptedException {
DeadlockPreventionDemo demo = new DeadlockPreventionDemo();
System.out.println("=== 锁排序策略测试 ===");
Thread[] orderingThreads = new Thread[5];
for (int i = 0; i < 5; i++) {
orderingThreads[i] = new Thread(demo::lockOrderingStrategy, "OrderingThread-" + i);
orderingThreads[i].start();
}
for (Thread t : orderingThreads) {
t.join();
}
System.out.println("\n=== 超时策略测试 ===");
Thread[] timeoutThreads = new Thread[5];
for (int i = 0; i < 5; i++) {
timeoutThreads[i] = new Thread(demo::timeoutStrategy, "TimeoutThread-" + i);
timeoutThreads[i].start();
}
for (Thread t : timeoutThreads) {
t.join();
}
System.out.println("\n=== 回退策略测试 ===");
Thread[] backoffThreads = new Thread[5];
for (int i = 0; i < 5; i++) {
backoffThreads[i] = new Thread(demo::backoffStrategy, "BackoffThread-" + i);
backoffThreads[i].start();
}
for (Thread t : backoffThreads) {
t.join();
}
}
}
# 7. 锁的最佳实践
# 7.1 锁的选择指南
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.StampedLock;
public class LockSelectionGuide {
// 场景1: 简单的互斥访问 - 使用synchronized
private int simpleCounter = 0;
public synchronized void incrementSimple() {
simpleCounter++;
}
// 场景2: 需要可中断、超时、公平性 - 使用ReentrantLock
private final ReentrantLock advancedLock = new ReentrantLock(true); // 公平锁
private int advancedCounter = 0;
public void incrementAdvanced() throws InterruptedException {
if (advancedLock.tryLock(1000, java.util.concurrent.TimeUnit.MILLISECONDS)) {
try {
advancedCounter++;
} finally {
advancedLock.unlock();
}
} else {
System.out.println("Failed to acquire lock within timeout");
}
}
// 场景3: 读多写少 - 使用ReadWriteLock
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
private String data = "initial";
public String readData() {
rwLock.readLock().lock();
try {
// 模拟读操作
Thread.sleep(10);
return data;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return null;
} finally {
rwLock.readLock().unlock();
}
}
public void writeData(String newData) {
rwLock.writeLock().lock();
try {
// 模拟写操作
Thread.sleep(50);
data = newData;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
rwLock.writeLock().unlock();
}
}
// 场景4: 读操作极其频繁,写操作很少 - 使用StampedLock
private final StampedLock stampedLock = new StampedLock();
private double x = 0.0, y = 0.0;
public double calculateDistance() {
long stamp = stampedLock.tryOptimisticRead();
double curX = x, curY = y;
if (!stampedLock.validate(stamp)) {
// 乐观读失败,使用悲观读
stamp = stampedLock.readLock();
try {
curX = x;
curY = y;
} finally {
stampedLock.unlockRead(stamp);
}
}
return Math.sqrt(curX * curX + curY * curY);
}
public void updateCoordinates(double newX, double newY) {
long stamp = stampedLock.writeLock();
try {
x = newX;
y = newY;
} finally {
stampedLock.unlockWrite(stamp);
}
}
public static void main(String[] args) {
LockSelectionGuide guide = new LockSelectionGuide();
System.out.println("锁选择指南:");
System.out.println("1. 简单互斥访问 -> synchronized");
System.out.println("2. 需要高级功能(超时、中断、公平性) -> ReentrantLock");
System.out.println("3. 读多写少场景 -> ReentrantReadWriteLock");
System.out.println("4. 读操作极其频繁 -> StampedLock");
}
}
# 7.2 锁优化技巧
import java.util.concurrent.locks.ReentrantLock;
public class LockOptimizationTips {
private final ReentrantLock lock = new ReentrantLock();
private int counter = 0;
// 技巧1: 减少锁的持有时间
public void badExample() {
lock.lock();
try {
// 不好的做法:在锁内进行耗时操作
counter++;
expensiveOperation(); // 耗时操作
counter++;
} finally {
lock.unlock();
}
}
public void goodExample() {
// 好的做法:将耗时操作移到锁外
expensiveOperation(); // 耗时操作移到锁外
lock.lock();
try {
counter++;
counter++;
} finally {
lock.unlock();
}
}
// 技巧2: 减少锁的粒度
private final ReentrantLock lock1 = new ReentrantLock();
private final ReentrantLock lock2 = new ReentrantLock();
private int counter1 = 0;
private int counter2 = 0;
public void coarseGrainedLock() {
// 粗粒度锁:一个锁保护多个资源
lock.lock();
try {
counter1++;
counter2++;
} finally {
lock.unlock();
}
}
public void fineGrainedLock() {
// 细粒度锁:每个资源使用独立的锁
lock1.lock();
try {
counter1++;
} finally {
lock1.unlock();
}
lock2.lock();
try {
counter2++;
} finally {
lock2.unlock();
}
}
// 技巧3: 使用tryLock避免阻塞
public boolean tryIncrementWithTimeout() {
try {
if (lock.tryLock(100, java.util.concurrent.TimeUnit.MILLISECONDS)) {
try {
counter++;
return true;
} finally {
lock.unlock();
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return false;
}
// 技巧4: 锁分离
private final ReentrantLock readLock = new ReentrantLock();
private final ReentrantLock writeLock = new ReentrantLock();
private volatile boolean dataReady = false;
public void readOperation() {
readLock.lock();
try {
if (dataReady) {
// 执行读操作
System.out.println("Reading data...");
}
} finally {
readLock.unlock();
}
}
public void writeOperation() {
writeLock.lock();
try {
// 执行写操作
dataReady = true;
System.out.println("Writing data...");
} finally {
writeLock.unlock();
}
}
private void expensiveOperation() {
try {
Thread.sleep(100); // 模拟耗时操作
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
public static void main(String[] args) {
LockOptimizationTips tips = new LockOptimizationTips();
System.out.println("锁优化技巧:");
System.out.println("1. 减少锁的持有时间");
System.out.println("2. 减少锁的粒度");
System.out.println("3. 使用tryLock避免阻塞");
System.out.println("4. 锁分离");
System.out.println("5. 避免在锁内调用其他同步方法");
System.out.println("6. 使用并发容器替代同步容器");
}
}
# 8. 总结
Java锁机制是并发编程的核心,本文详细介绍了:
# 8.1 核心要点
synchronized关键字
- 基于对象头和Monitor实现
- 支持锁升级(偏向锁→轻量级锁→重量级锁)
- JVM自动优化(锁消除、锁粗化、适应性自旋)
ReentrantLock显式锁
- 基于AQS(AbstractQueuedSynchronizer)实现
- 支持可重入、公平/非公平、可中断、超时等高级特性
- 需要手动释放锁,使用try-finally确保释放
读写锁机制
- ReentrantReadWriteLock:读读共享,读写互斥,写写互斥
- StampedLock:支持乐观读,性能更优
- 适用于读多写少的场景
性能与选择
- synchronized:简单场景,JVM优化好
- ReentrantLock:需要高级功能时
- ReadWriteLock:读多写少场景
- StampedLock:读操作极其频繁的场景
# 8.2 最佳实践
锁的选择原则
- 优先使用synchronized,除非需要高级功能
- 读多写少场景使用读写锁
- 避免过度使用锁,考虑无锁数据结构
性能优化策略
- 减少锁的持有时间
- 减少锁的粒度
- 避免在锁内进行耗时操作
- 使用tryLock避免无限等待
死锁预防
- 锁排序:始终按相同顺序获取锁
- 超时机制:使用tryLock设置超时
- 回退策略:获取失败时主动释放已持有的锁
# 8.3 发展趋势
- 无锁编程:使用原子类、CAS操作
- 并发容器:ConcurrentHashMap、CopyOnWriteArrayList等
- 异步编程:CompletableFuture、响应式编程
- 虚拟线程:Project Loom带来的轻量级线程
理解和掌握Java锁机制对于编写高性能、线程安全的并发程序至关重要。在实际开发中,应根据具体场景选择合适的锁机制,并遵循最佳实践来避免常见的并发问题。
# 1.2 锁的分类
悲观锁 vs 乐观锁
- 悲观锁:假设会发生并发冲突,每次访问都加锁
- 乐观锁:假设不会发生冲突,只在更新时检查
公平锁 vs 非公平锁
- 公平锁:按照请求锁的顺序获取锁
- 非公平锁:不保证获取锁的顺序
可重入锁 vs 不可重入锁
- 可重入锁:同一线程可以多次获取同一把锁
- 不可重入锁:同一线程不能多次获取同一把锁
独享锁 vs 共享锁
- 独享锁:只能被一个线程持有(如写锁)
- 共享锁:可以被多个线程同时持有(如读锁)
# 2. synchronized实现原理
# 2.1 synchronized的使用方式
public class SynchronizedDemo {
private int count = 0;
private static int staticCount = 0;
// 1. 修饰实例方法
public synchronized void instanceMethod() {
count++;
System.out.println("Instance method: " + count);
}
// 2. 修饰静态方法
public static synchronized void staticMethod() {
staticCount++;
System.out.println("Static method: " + staticCount);
}
// 3. 修饰代码块
public void blockMethod() {
synchronized (this) {
count++;
System.out.println("Block method: " + count);
}
}
// 4. 修饰静态代码块
public void staticBlockMethod() {
synchronized (SynchronizedDemo.class) {
staticCount++;
System.out.println("Static block method: " + staticCount);
}
}
public static void main(String[] args) throws InterruptedException {
SynchronizedDemo demo = new SynchronizedDemo();
// 测试不同的synchronized使用方式
Thread t1 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
demo.instanceMethod();
SynchronizedDemo.staticMethod();
demo.blockMethod();
demo.staticBlockMethod();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
demo.instanceMethod();
SynchronizedDemo.staticMethod();
demo.blockMethod();
demo.staticBlockMethod();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}
# 2.2 synchronized的底层实现
# 2.2.1 对象头和Monitor
public class ObjectHeaderDemo {
private final Object lock = new Object();
public void demonstrateObjectHeader() {
synchronized (lock) {
// 在这个代码块中,lock对象的对象头会被修改
// Mark Word会存储指向Monitor对象的指针
System.out.println("Inside synchronized block");
// 可以通过JOL(Java Object Layout)工具查看对象头信息
// System.out.println(ClassLayout.parseInstance(lock).toPrintable());
}
}
public static void main(String[] args) {
ObjectHeaderDemo demo = new ObjectHeaderDemo();
demo.demonstrateObjectHeader();
}
}
# 2.2.2 锁升级过程
public class LockUpgradeDemo {
private int count = 0;
public void demonstrateLockUpgrade() {
// 1. 无锁状态 -> 偏向锁
// 当第一个线程访问时,会升级为偏向锁
synchronized (this) {
count++;
System.out.println("First access - Biased Lock");
}
// 2. 偏向锁 -> 轻量级锁
// 当有第二个线程竞争时,会升级为轻量级锁
Thread t1 = new Thread(() -> {
synchronized (this) {
count++;
System.out.println("Second thread - Lightweight Lock");
}
});
t1.start();
try {
t1.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 3. 轻量级锁 -> 重量级锁
// 当竞争激烈时,会升级为重量级锁
Thread[] threads = new Thread[10];
for (int i = 0; i < 10; i++) {
threads[i] = new Thread(() -> {
synchronized (this) {
count++;
try {
Thread.sleep(10); // 增加竞争
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
threads[i].start();
}
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
System.out.println("Final count: " + count);
}
public static void main(String[] args) {
LockUpgradeDemo demo = new LockUpgradeDemo();
demo.demonstrateLockUpgrade();
}
}
# 2.3 synchronized的性能优化
public class SynchronizedOptimizationDemo {
private int count = 0;
private final Object lock = new Object();
// 锁消除示例
public void lockElimination() {
// JVM会检测到这个StringBuffer只在方法内部使用
// 不会被其他线程访问,因此会消除synchronized
StringBuffer sb = new StringBuffer();
sb.append("Hello");
sb.append(" World");
System.out.println(sb.toString());
}
// 锁粗化示例
public void lockCoarsening() {
// 原本的细粒度锁
synchronized (lock) {
count++;
}
synchronized (lock) {
count++;
}
synchronized (lock) {
count++;
}
// JVM会将上述代码优化为:
// synchronized (lock) {
// count++;
// count++;
// count++;
// }
}
// 适应性自旋示例
public void adaptiveSpinning() {
Thread[] threads = new Thread[5];
for (int i = 0; i < 5; i++) {
threads[i] = new Thread(() -> {
synchronized (lock) {
// 短时间持有锁,适合自旋等待
count++;
System.out.println(Thread.currentThread().getName() + ": " + count);
}
}, "Thread-" + i);
}
for (Thread thread : threads) {
thread.start();
}
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
public static void main(String[] args) {
SynchronizedOptimizationDemo demo = new SynchronizedOptimizationDemo();
System.out.println("=== 锁消除演示 ===");
demo.lockElimination();
System.out.println("\n=== 锁粗化演示 ===");
demo.lockCoarsening();
System.out.println("\n=== 适应性自旋演示 ===");
demo.adaptiveSpinning();
}
}