Java锁全面指南:从基础概念到企业级应用

Java锁全面指南:从基础概念到企业级应用

目录

  1. 锁的基本概念
  2. Java中的锁分类
  3. synchronized关键字
  4. ReentrantLock
  5. 读写锁ReadWriteLock
  6. StampedLock
  7. CAS与原子类
  8. 并发容器中的锁
  9. 分布式锁
  10. 锁的性能优化
  11. 企业级应用场景
  12. 最佳实践与常见问题

锁的基本概念

什么是锁?

锁是多线程编程中用于控制对共享资源访问的同步机制。当多个线程同时访问共享资源时,锁可以确保同一时刻只有一个线程能够执行临界区代码,从而避免数据竞争和不一致性问题。

为什么需要锁?

// 没有锁保护的情况下可能出现的问题
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

特性ReentrantLocksynchronized
可中断支持不支持
超时获取支持不支持
公平性可选非公平
条件变量多个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

特性StampedLockReadWriteLock
乐观读支持不支持
性能更高较低
可重入不支持支持
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锁机制是并发编程的核心,理解各种锁的特性和适用场景对于编写高质量的并发程序至关重要。在实际应用中,应该:

  1. 根据场景选择合适的锁:单机环境优先考虑JDK内置锁,分布式环境使用分布式锁
  2. 优化锁的使用:减小锁粒度、缩短持有时间、避免锁嵌套
  3. 注意性能和安全性平衡:不要过度优化,也不要忽视潜在的并发问题
  4. 充分测试:使用压力测试验证锁的正确性和性能

掌握这些知识,你将能够在企业级应用中游刃有余地处理各种并发场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值