Java锁
在 Java 中,锁(Lock)是用于控制多线程对共享资源访问的机制,确保线程安全。Java 提供了多种锁机制,主要包括以下几种:
1. synchronized
关键字
synchronized
是 Java 中最基本的锁机制,可以用于方法或代码块。
用法
-
修饰实例方法:锁住当前对象实例。
public synchronized void method() { // 线程安全的代码 }
-
修饰静态方法:锁住当前类的 Class 对象。
public static synchronized void staticMethod() { // 线程安全的代码 }
-
修饰代码块:锁住指定对象。
public void method() { synchronized (this) { // 锁住当前对象 // 线程安全的代码 } }
特点
-
简单易用,无需手动释放锁。
-
不支持超时、中断等高级功能。
-
性能较低,适合简单的同步场景。
2. ReentrantLock
ReentrantLock
是 java.util.concurrent.locks
包中的锁实现,提供了比 synchronized
更强大的功能。
用法
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Example { private final Lock lock = new ReentrantLock(); public void method() { lock.lock(); // 加锁 try { // 线程安全的代码 } finally { lock.unlock(); // 释放锁 } } }
特点
-
支持可重入(同一个线程可以多次获取锁)。
-
支持公平锁和非公平锁(默认是非公平锁)。
-
支持超时获取锁、可中断获取锁等高级功能。
if (lock.tryLock(1, TimeUnit.SECONDS)) { // 尝试获取锁,最多等待 1 秒 try { // 线程安全的代码 } finally { lock.unlock(); } } else { // 未获取到锁的处理逻辑 }
3. ReadWriteLock
ReadWriteLock
是一种读写锁,允许多个读线程同时访问,但写线程独占访问。
用法
import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class Example { private final ReadWriteLock rwLock = new ReentrantReadWriteLock(); public void readMethod() { rwLock.readLock().lock(); // 加读锁 try { // 读操作 } finally { rwLock.readLock().unlock(); // 释放读锁 } } public void writeMethod() { rwLock.writeLock().lock(); // 加写锁 try { // 写操作 } finally { rwLock.writeLock().unlock(); // 释放写锁 } } }
特点
-
读写分离,提高并发性能。
-
写锁是独占锁,读锁是共享锁。
4. StampedLock
StampedLock
是 Java 8 引入的一种更高效的读写锁,支持乐观读锁。
用法
import java.util.concurrent.locks.StampedLock; public class Example { private final StampedLock stampedLock = new StampedLock(); public void readMethod() { long stamp = stampedLock.tryOptimisticRead(); // 尝试乐观读 // 读操作 if (!stampedLock.validate(stamp)) { // 检查是否被写操作修改 stamp = stampedLock.readLock(); // 获取悲观读锁 try { // 读操作 } finally { stampedLock.unlockRead(stamp); // 释放读锁 } } } public void writeMethod() { long stamp = stampedLock.writeLock(); // 获取写锁 try { // 写操作 } finally { stampedLock.unlockWrite(stamp); // 释放写锁 } } }
特点
-
支持乐观读锁,减少锁竞争。
-
比
ReadWriteLock
性能更高,但使用更复杂。
5. 其他锁
-
Condition
:与ReentrantLock
配合使用,实现线程间的等待/通知机制。Lock lock = new ReentrantLock(); Condition condition = lock.newCondition(); lock.lock(); try { condition.await(); // 等待 condition.signal(); // 唤醒 } finally { lock.unlock(); }
-
Semaphore
:信号量,用于控制同时访问资源的线程数量。Semaphore semaphore = new Semaphore(10); // 允许 10 个线程同时访问 semaphore.acquire(); // 获取许可 try { // 访问资源 } finally { semaphore.release(); // 释放许可 }
-
CountDownLatch
:倒计时锁,用于等待多个线程完成任务。CountDownLatch latch = new CountDownLatch(3); // 需要等待 3 个线程 latch.await(); // 等待 latch.countDown(); // 完成任务
-
CyclicBarrier
:循环屏障,用于多个线程相互等待。CyclicBarrier barrier = new CyclicBarrier(3); // 3 个线程相互等待 barrier.await(); // 等待其他线程
总结
锁机制 | 特点 |
---|---|
synchronized | 简单易用,性能较低,适合简单场景。 |
ReentrantLock | 功能强大,支持可重入、公平锁、超时、中断等。 |
ReadWriteLock | 读写分离,提高并发性能。 |
StampedLock | 高性能读写锁,支持乐观读锁。 |
Condition | 与 ReentrantLock 配合使用,实现线程间通信。 |
Semaphore | 控制同时访问资源的线程数量。 |
CountDownLatch | 等待多个线程完成任务。 |
CyclicBarrier | 多个线程相互等待。 |
根据具体需求选择合适的锁机制。对于高并发场景,推荐使用 ReentrantLock
或 StampedLock
。