Java锁全面指南:从基础概念到企业级应用
目录
- 锁的基本概念
- Java中的锁分类
- synchronized关键字
- ReentrantLock
- 读写锁ReadWriteLock
- StampedLock
- CAS与原子类
- 并发容器中的锁
- 分布式锁
- 锁的性能优化
- 企业级应用场景
- 最佳实践与常见问题
锁的基本概念
什么是锁?
锁是多线程编程中用于控制对共享资源访问的同步机制。当多个线程同时访问共享资源时,锁可以确保同一时刻只有一个线程能够执行临界区代码,从而避免数据竞争和不一致性问题。
为什么需要锁?
// 没有锁保护的情况下可能出现的问题
public class Counter {
private int count = 0;
// 多线程环境下不安全
public void increment() {
count++; // 这是一个复合操作:读取 -> 加1 -> 写入
}
public int getCount() {
return count;
}
}
锁的核心特性
| 特性 |
说明 |
| 互斥性 |
同一时刻只有一个线程能持有锁 |
| 可见性 |
一个线程释放锁后,其他线程能看到其修改 |
| 有序性 |
保证程序执行的顺序性 |
| 原子性 |
确保操作的原子性 |
Java中的锁分类
按乐观/悲观分类
锁分类
├── 悲观锁 (Pessimistic Lock)
│ ├── synchronized
│ ├── ReentrantLock
│ └── 数据库行锁/表锁
│
└── 乐观锁 (Optimistic Lock)
├── CAS操作
├── 版本号机制
└── 数据库乐观锁
按公平性分类
公平性
├── 公平锁 (Fair Lock)
│ └── 按线程请求顺序获取锁
│
└── 非公平锁 (Unfair Lock)
└── 允许插队,性能更好
按可重入性分类
可重入性
├── 可重入锁 (Reentrant Lock)
│ └── 同一线程可多次获取同一把锁
│
└── 不可重入锁 (Non-reentrant Lock)
└── 同一线程再次获取会死锁
synchronized关键字
基本用法
public class SynchronizedDemo {
// 1. 修饰实例方法 - 锁定当前实例
public synchronized void method1() {
// 同一时刻只有一个线程能执行
}
// 2. 修饰静态方法 - 锁定Class对象
public static synchronized void method2() {
// 所有实例共享这把锁
}
// 3. 修饰代码块 - 锁定指定对象
public void method3() {
synchronized (this) {
// 只锁定部分代码
}
}
// 4. 锁定类的Class对象
public void method4() {
synchronized (SynchronizedDemo.class) {
// 效果同静态方法
}
}
}
底层原理
synchronized执行流程
┌─────────────────────────────────────────────────────────┐
│ synchronized代码块 │
├─────────────────────────────────────────────────────────┤
│ monitorenter指令 ──→ 获取Monitor对象 ──→ 进入同步块 │
├─────────────────────────────────────────────────────────┤
│ 执行同步代码 │
├─────────────────────────────────────────────────────────┤
│ monitorexit指令 ──→ 释放Monitor对象 ──→ 退出同步块 │
└─────────────────────────────────────────────────────────┘
synchronized的优化历程
Java版本优化
├── JDK 1.6之前
│ └── 纯粹的重量级锁(依赖操作系统Mutex Lock)
│
├── JDK 1.6
│ ├── 偏向锁 (Biased Locking)
│ ├── 轻量级锁 (Lightweight Lock)
│ ├── 重量级锁 (Heavyweight Lock)
│ └── 自旋锁 (Spin Lock)
│
└── 锁升级过程
无锁 → 偏向锁 → 轻量级锁 → 重量级锁
锁升级详解
// 偏向锁:只有一个线程访问时
// 在对象头中记录线程ID,后续同一线程进入时直接验证
// 轻量级锁:少量竞争时
// 通过CAS尝试获取锁,失败则自旋等待
// 重量级锁:竞争激烈时
// 依赖操作系统内核的Mutex Lock
ReentrantLock
基本用法
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockDemo {
private final ReentrantLock lock = new ReentrantLock();
public void safeMethod() {
lock.lock();
try {
// 临界区代码
} finally {
lock.unlock(); // 必须在finally中释放锁
}
}
}
高级特性
public class ReentrantLockAdvanced {
private final ReentrantLock lock = new ReentrantLock();
// 1. 可中断的锁获取
public void interruptibleMethod() throws InterruptedException {
lock.lockInterruptibly();
try {
// 可以被中断的临界区
} finally {
lock.unlock();
}
}
// 2. 尝试非阻塞获取锁
public void tryLockMethod() {
if (lock.tryLock()) {
try {
// 获取到锁
} finally {
lock.unlock();
}
} else {
// 未获取到锁,执行其他逻辑
}
}
// 3. 超时获取锁
public void timedLockMethod() throws InterruptedException {
if (lock.tryLock(5, TimeUnit.SECONDS)) {
try {
// 5秒内获取到锁
} finally {
lock.unlock();
}
} else {
// 超时未获取到锁
}
}
// 4. 公平锁
public ReentrantLock fairLock() {
return new ReentrantLock(true); // 公平锁
}
// 5. 条件变量
public void conditionMethod() throws InterruptedException {
Condition condition = lock.newCondition();
lock.lock();
try {
while (/* 条件不满足 */) {
condition.await(); // 等待
}
// 执行业务逻辑
} finally {
lock.unlock();
}
}
// 唤醒等待线程
public void signalMethod() {
lock.lock();
try {
condition.signal(); // 唤醒一个等待线程
// 或 condition.signalAll(); // 唤醒所有等待线程
} finally {
lock.unlock();
}
}
}
ReentrantLock vs synchronized
| 特性 |
ReentrantLock |
synchronized |
| 可中断 |
支持 |
不支持 |
| 超时获取 |
支持 |
不支持 |
| 公平性 |
可选 |
非公平 |
| 条件变量 |
多个Condition |
只有一个wait/notify |
| 性能 |
JDK 6+后差不多 |
JDK 6+后优化 |
| 锁释放 |
必须手动释放 |
自动释放 |
读写锁ReadWriteLock
基本概念
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteLockDemo {
private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
private final Lock readLock = rwLock.readLock();
private final Lock writeLock = rwLock.writeLock();
private Map<String, Object> cache = new HashMap<>();
// 读操作 - 多个线程可以同时读
public Object read(String key) {
readLock.lock();
try {
return cache.get(key);
} finally {
readLock.unlock();
}
}
// 写操作 - 独占访问
public void write(String key, Object value) {
writeLock.lock();
try {
cache.put(key, value);
} finally {
writeLock.unlock();
}
}
}
读写锁的state设计
ReentrantReadWriteLock的state (int类型,32位)
├── 高16位:记录读锁持有次数
└── 低16位:记录写锁重入次数
锁降级与锁升级
// 锁降级:持有写锁时,可以获取读锁,然后释放写锁
public void lockDowngrade() {
writeLock.lock();
try {
// 修改数据
readLock.lock(); // 降级:获取读锁
} finally {
writeLock.unlock(); // 释放写锁
}
try {
// 继续持有读锁
} finally {
readLock.unlock();
}
}
// 锁升级:读锁不能直接升级为写锁
// 必须先释放读锁,再获取写锁
StampedLock
三种模式
import java.util.concurrent.locks.StampedLock;
public class StampedLockDemo {
private final StampedLock sl = new StampedLock();
private double x, y;
// 1. 写锁(独占)
public void move(double deltaX, double deltaY) {
long stamp = sl.writeLock();
try {
x += deltaX;
y += deltaY;
} finally {
sl.unlockWrite(stamp);
}
}
// 2. 乐观读(不加锁,性能最好)
public double distanceFromOrigin() {
long stamp = sl.tryOptimisticRead(); // 获取版本号
double currentX = x, currentY = y;
if (!sl.validate(stamp)) { // 验证版本号
// 乐观读失败,升级为悲观读
stamp = sl.readLock();
try {
currentX = x;
currentY = y;
} finally {
sl.unlockRead(stamp);
}
}
return Math.sqrt(currentX * currentX + currentY * currentY);
}
// 3. 悲观读
public void readOnly() {
long stamp = sl.readLock();
try {
// 读操作
} finally {
sl.unlockRead(stamp);
}
}
}
StampedLock vs ReadWriteLock
| 特性 |
StampedLock |
ReadWriteLock |
| 乐观读 |
支持 |
不支持 |
| 性能 |
更高 |
较低 |
| 可重入 |
不支持 |
支持 |
| Condition |
不支持 |
支持 |
| 公平性 |
不支持 |
可选 |
CAS与原子类
CAS原理
CAS (Compare-And-Swap)
┌─────────────────────────────────────────────────────────┐
│ 比较内存中的值与期望值 │
│ 如果相等,则更新为新值 │
│ 否则,什么都不做 │
└─────────────────────────────────────────────────────────┘
三个操作数:
- V: 内存地址(要更新的变量)
- E: 期望值(旧值)
- N: 新值(要写入的值)
if (V == E) {
V = N;
return true;
} else {
return false;
}
原子类
import java.util.concurrent.atomic.*;
public class AtomicDemo {
// 原子整数
private AtomicInteger atomicInt = new AtomicInteger(0);
// 原子引用
private AtomicReference<Object> atomicRef = new AtomicReference<>();
// 原子数组
private AtomicIntegerArray atomicArray = new AtomicIntegerArray(10);
// 原子字段更新器
private AtomicIntegerFieldUpdater<User> userUpdater =
AtomicIntegerFieldUpdater.newUpdater(User.class, "age");
public void atomicOperations() {
// 原子自增
atomicInt.incrementAndGet();
// CAS操作
atomicInt.compareAndSet(5, 10);
// 原子更新
atomicInt.updateAndGet(x -> x * 2);
}
// LongAdder(JDK 8+)- 高并发下性能更好
private LongAdder longAdder = new LongAdder();
public void add() {
longAdder.add(1);
}
public long sum() {
return longAdder.sum();
}
}
ABA问题
// ABA问题示例
// 线程1: 读取值为A,准备改为C
// 线程2: 将A改为B,再改回A
// 线程1: CAS发现值仍为A,成功改为C(但实际上值已经被修改过)
// 解决方案:使用版本号
AtomicStampedReference<Integer> stampedRef =
new AtomicStampedReference<>(1, 0); // 值和版本号
int stamp = stampedRef.getStamp(); // 获取版本号
Integer value = stampedRef.getReference(); // 获取值
// CAS时需要同时比较值和版本号
stampedRef.compareAndSet(1, 2, stamp, stamp + 1);
并发容器中的锁
ConcurrentHashMap
// JDK 7: Segment分段锁
// 将数据分为16个Segment,每个Segment有独立的锁
// JDK 8: CAS + synchronized
// 使用CAS进行初始化,使用synchronized锁定单个桶
public class ConcurrentHashMapDemo {
private ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<>();
// 线程安全的操作
public void safeOperations() {
map.put("key", "value");
map.putIfAbsent("key", "value");
map.compute("key", (k, v) -> v == null ? "default" : v);
map.merge("key", 1, (old, newVal) -> (int) old + (int) newVal);
}
}
其他并发容器
// ConcurrentLinkedQueue - 无锁队列(CAS实现)
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
// BlockingQueue - 阻塞队列
LinkedBlockingQueue<String> blockingQueue = new LinkedBlockingQueue<>();
blockingQueue.put("item"); // 阻塞直到有空间
blockingQueue.take(); // 阻塞直到有元素
// CopyOnWriteArrayList - 写时复制
CopyOnWriteArrayList<String> cowList = new CopyOnWriteArrayList<>();
// 读多写少时性能好
分布式锁
基于Redis实现
import redis.clients.jedis.Jedis;
import java.util.UUID;
public class RedisDistributedLock {
private static final String LOCK_PREFIX = "lock:";
private static final long LOCK_EXPIRE = 30000; // 30秒
private Jedis jedis;
private String lockKey;
private String lockValue;
private ThreadLocal<String> threadLocal = new ThreadLocal<>();
// 获取锁
public boolean tryLock(String key) {
lockKey = LOCK_PREFIX + key;
lockValue = UUID.randomUUID().toString();
String result = jedis.set(lockKey, lockValue, "NX", "PX", LOCK_EXPIRE);
if ("OK".equals(result)) {
threadLocal.set(lockValue);
return true;
}
return false;
}
// 释放锁(Lua脚本保证原子性)
public boolean unlock() {
String script =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
Object result = jedis.eval(script,
Collections.singletonList(lockKey),
Collections.singletonList(threadLocal.get()));
return Long.valueOf(result.toString()) == 1;
}
}
基于ZooKeeper实现
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import java.util.concurrent.CountDownLatch;
public class ZookeeperDistributedLock {
private ZooKeeper zookeeper;
private String lockPath;
private CountDownLatch latch;
// 获取锁
public void lock(String key) throws Exception {
lockPath = "/locks/" + key + "/" + System.nanoTime();
// 创建临时顺序节点
zookeeper.create(lockPath, new byte[0],
ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
// 检查是否是最小节点
while (true) {
Stat stat = new Stat();
byte[] data = zookeeper.getData("/locks/" + key, false, stat);
// 获取所有子节点
List<String> children = zookeeper.getChildren("/locks/" + key, false);
Collections.sort(children);
if (lockPath.endsWith(children.get(0))) {
// 是最小节点,获取锁成功
return;
}
// 等待前一个节点删除
latch = new CountDownLatch(1);
Stat watchStat = zookeeper.exists("/locks/" + key + "/" +
children.get(children.indexOf(lockPath.replace("/locks/" + key + "/", "")) - 1),
event -> {
if (event.getType() == Watcher.Event.EventType.NodeDeleted) {
latch.countDown();
}
});
if (watchStat != null) {
latch.await();
}
}
}
// 释放锁
public void unlock() throws Exception {
zookeeper.delete(lockPath, -1);
}
}
基于数据库实现
-- 创建锁表
CREATE TABLE distributed_lock (
lock_key VARCHAR(255) PRIMARY KEY,
lock_value VARCHAR(255) NOT NULL,
expire_time DATETIME NOT NULL,
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- 获取锁
INSERT INTO distributed_lock (lock_key, lock_value, expire_time)
VALUES ('order_lock', 'uuid_value', DATE_ADD(NOW(), INTERVAL 30 SECOND))
ON DUPLICATE KEY UPDATE
lock_value = IF(expire_time < NOW(), VALUES(lock_value), lock_value),
expire_time = IF(expire_time < NOW(), VALUES(expire_time), expire_time);
-- 释放锁
DELETE FROM distributed_lock
WHERE lock_key = 'order_lock' AND lock_value = 'uuid_value';
分布式锁对比
| 实现方式 |
优点 |
缺点 |
适用场景 |
| Redis |
性能高,实现简单 |
需要处理主从同步 |
高并发、低延迟 |
| ZooKeeper |
可靠性高,支持公平锁 |
性能较低 |
强一致性要求 |
| 数据库 |
实现简单,易于理解 |
性能最低 |
低并发场景 |
锁的性能优化
1. 减少锁持有时间
// 不好的做法
public void badPractice() {
lock.lock();
try {
// 大量非同步代码
doSomethingUnnecessary();
doCriticalSection();
doSomethingElse();
} finally {
lock.unlock();
}
}
// 好的做法
public void goodPractice() {
doSomethingUnnecessary();
lock.lock();
try {
doCriticalSection();
} finally {
lock.unlock();
}
doSomethingElse();
}
2. 降低锁粒度
// 粗粒度锁
public class CoarseLock {
private final Object lock = new Object();
private Map<String, Object> map = new HashMap<>();
public void put(String key, Object value) {
synchronized (lock) { // 所有操作共享一把锁
map.put(key, value);
}
}
}
// 细粒度锁
public class FineLock {
private Map<String, Object> map = new ConcurrentHashMap<>();
public void put(String key, Object value) {
map.put(key, value); // 每个操作独立
}
}
3. 使用读写锁
// 读多写少场景
public class ReadWriteOptimization {
private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
private final Lock readLock = rwLock.readLock();
private final Lock writeLock = rwLock.writeLock();
private Map<String, Object> data = new HashMap<>();
// 读操作可以并发
public Object read(String key) {
readLock.lock();
try {
return data.get(key);
} finally {
readLock.unlock();
}
}
// 写操作互斥
public void write(String key, Object value) {
writeLock.lock();
try {
data.put(key, value);
} finally {
writeLock.unlock();
}
}
}
4. 使用乐观锁
// 无锁编程
public class LockFreeOptimization {
private AtomicInteger counter = new AtomicInteger(0);
public void increment() {
counter.incrementAndGet(); // CAS实现,无锁
}
// LongAdder更适合高并发计数
private LongAdder longAdder = new LongAdder();
public void add() {
longAdder.add(1);
}
}
5. 避免锁嵌套
// 不好的做法 - 死锁风险
public void nestedLocks() {
lockA.lock();
try {
lockB.lock();
try {
// 业务逻辑
} finally {
lockB.unlock();
}
} finally {
lockA.unlock();
}
}
// 好的做法 - 避免嵌套
public void avoidNestedLocks() {
lockA.lock();
try {
// 业务逻辑1
} finally {
lockA.unlock();
}
lockB.lock();
try {
// 业务逻辑2
} finally {
lockB.unlock();
}
}
企业级应用场景
1. 订单号生成
@Service
public class OrderService {
@Autowired
private RedisDistributedLock redisLock;
@Autowired
private OrderMapper orderMapper;
public String generateOrderNo() {
String lockKey = "order_no_lock";
boolean locked = redisLock.tryLock(lockKey);
try {
if (locked) {
// 获取当前最大订单号
String maxOrderNo = orderMapper.getMaxOrderNo();
// 生成新订单号
return generateNextOrderNo(maxOrderNo);
} else {
throw new RuntimeException("获取锁失败");
}
} finally {
if (locked) {
redisLock.unlock();
}
}
}
private String generateNextOrderNo(String maxOrderNo) {
if (maxOrderNo == null) {
return "ORD" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")) + "000001";
}
// 解析并递增
String datePart = maxOrderNo.substring(3, 11);
int seq = Integer.parseInt(maxOrderNo.substring(11)) + 1;
return "ORD" + datePart + String.format("%06d", seq);
}
}
2. 库存扣减
@Service
public class StockService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
// Redis + Lua脚本实现原子扣减
private static final String DEDUCT_SCRIPT =
"local stock = tonumber(redis.call('get', KEYS[1])) " +
"if stock and stock >= tonumber(ARGV[1]) then " +
" redis.call('decrby', KEYS[1], ARGV[1]) " +
" return 1 " +
"else " +
" return 0 " +
"end";
public boolean deductStock(String skuId, int quantity) {
Long result = redisTemplate.execute(
new DefaultRedisScript<>(DEDUCT_SCRIPT, Long.class),
Collections.singletonList("stock:" + skuId),
String.valueOf(quantity)
);
return result != null && result == 1;
}
// 数据库乐观锁实现
@Transactional
public boolean deductStockWithDB(String skuId, int quantity) {
int version = stockMapper.getVersion(skuId);
int rows = stockMapper.deductStock(skuId, quantity, version);
return rows > 0;
}
}
3. 缓存击穿防护
@Service
public class CacheService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private ReentrantLock lock = new ReentrantLock();
// 缓存击穿防护
public Object getData(String key) {
// 1. 先查缓存
Object value = redisTemplate.opsForValue().get(key);
if (value != null) {
return value;
}
// 2. 缓存未命中,加锁加载
lock.lock();
try {
// 双重检查
value = redisTemplate.opsForValue().get(key);
if (value != null) {
return value;
}
// 3. 从数据库加载
value = loadFromDB(key);
// 4. 写入缓存
redisTemplate.opsForValue().set(key, value, 30, TimeUnit.MINUTES);
return value;
} finally {
lock.unlock();
}
}
// 使用分布式锁的版本
public Object getDataWithDistributedLock(String key) {
Object value = redisTemplate.opsForValue().get(key);
if (value != null) {
return value;
}
String lockKey = "lock:" + key;
boolean locked = distributedLock.tryLock(lockKey);
try {
if (locked) {
value = loadFromDB(key);
redisTemplate.opsForValue().set(key, value, 30, TimeUnit.MINUTES);
return value;
} else {
// 等待其他线程加载
Thread.sleep(100);
return redisTemplate.opsForValue().get(key);
}
} finally {
if (locked) {
distributedLock.unlock();
}
}
}
}
4. 分布式任务调度
@Service
public class TaskScheduler {
@Autowired
private ZookeeperDistributedLock zkLock;
public void executeTask(String taskId) {
String lockKey = "task_lock_" + taskId;
try {
zkLock.lock(lockKey);
// 执行任务
doTask(taskId);
} catch (Exception e) {
log.error("任务执行失败", e);
} finally {
try {
zkLock.unlock();
} catch (Exception e) {
log.error("释放锁失败", e);
}
}
}
private void doTask(String taskId) {
// 具体业务逻辑
}
}
5. 接口限流
@Component
public class RateLimiter {
private final LoadingCache<String, AtomicInteger> counterCache;
public RateLimiter() {
counterCache = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.SECONDS)
.build(new CacheLoader<String, AtomicInteger>() {
@Override
public AtomicInteger load(String key) {
return new AtomicInteger(0);
}
});
}
public boolean isAllowed(String key, int maxRequests) {
try {
AtomicInteger counter = counterCache.get(key);
int current = counter.incrementAndGet();
return current <= maxRequests;
} catch (ExecutionException e) {
return false;
}
}
// 使用Redis实现分布式限流
public boolean isAllowedWithRedis(String key, int maxRequests, int windowSeconds) {
String redisKey = "rate:" + key;
Long count = redisTemplate.opsForValue().increment(redisKey);
if (count == 1) {
redisTemplate.expire(redisKey, windowSeconds, TimeUnit.SECONDS);
}
return count != null && count <= maxRequests;
}
}
最佳实践与常见问题
最佳实践
// 1. 始终在finally块中释放锁
lock.lock();
try {
// 业务逻辑
} finally {
lock.unlock();
}
// 2. 使用tryLock避免死锁
if (lock.tryLock(5, TimeUnit.SECONDS)) {
try {
// 业务逻辑
} finally {
lock.unlock();
}
} else {
// 超时处理
}
// 3. 优先使用并发工具类
// 使用ConcurrentHashMap代替Collections.synchronizedMap
// 使用CountDownLatch代替wait/notify
// 使用BlockingQueue实现生产者-消费者
// 4. 减小锁的范围
synchronized (lock) {
// 只同步必要的代码
}
// 5. 读写分离
// 读多写少使用ReadWriteLock
// 写多使用synchronized或ReentrantLock
常见问题与解决方案
| 问题 |
原因 |
解决方案 |
| 死锁 |
锁顺序不一致 |
固定锁顺序,使用tryLock |
| 活锁 |
线程一直重试 |
添加随机延迟 |
| 饥饿 |
低优先级线程无法获取锁 |
使用公平锁 |
| 性能下降 |
锁粒度太粗 |
降低锁粒度,使用读写锁 |
| 缓存击穿 |
热点数据过期 |
使用互斥锁或逻辑过期 |
锁选择指南
选择锁的决策流程
├── 单机环境
│ ├── 简单同步 → synchronized
│ ├── 需要超时/中断 → ReentrantLock
│ ├── 读多写少 → ReadWriteLock
│ ├── 高并发读 → StampedLock
│ └── 无锁优先 → 原子类
│
└── 分布式环境
├── 高性能要求 → Redis分布式锁
├── 高可靠性要求 → ZooKeeper分布式锁
└── 简单场景 → 数据库分布式锁
总结
Java锁机制是并发编程的核心,理解各种锁的特性和适用场景对于编写高质量的并发程序至关重要。在实际应用中,应该:
- 根据场景选择合适的锁:单机环境优先考虑JDK内置锁,分布式环境使用分布式锁
- 优化锁的使用:减小锁粒度、缩短持有时间、避免锁嵌套
- 注意性能和安全性平衡:不要过度优化,也不要忽视潜在的并发问题
- 充分测试:使用压力测试验证锁的正确性和性能
掌握这些知识,你将能够在企业级应用中游刃有余地处理各种并发场景。