👀 分布式锁(Lock)和同步器(Synchronizer)
名称 | 作用 | 使用场景 | 优点 | 缺点 | Redisson调用的方法 |
---|---|---|---|---|---|
分布式锁 & 同步器 | 多节点进程间同步 | 分布式系统中确保资源唯一访问 | 资源唯一访问,避免数据不一致 | 系统复杂性增加 | — |
可重入锁 | 同一线程多次获取的锁 | 线程需多次进入已锁定代码块 | 避免死锁,比synchronized灵活 | 需手动释放锁 | getLock |
公平锁 | 确保等待最长的线程首先获得锁 | 需确保所有线程公平访问资源 | 所有线程的公平访问 | 性能低于非公平锁 | getFairLock |
联锁 | 所有锁被同时获取 | 多个资源都需锁定完成操作 | 确保所有必要资源锁定 | 更复杂,死锁风险增加 | getMultiLock |
红锁 | 多Redis节点上的分布式锁 | Redis集群中确保资源唯一访问 | 提高Redis集群中锁的可靠性 | 需多Redis实例 | RedissonRedLock |
读写锁 | 允许多线程读,单线程写 | 多线程读,单线程修改资源 | 提高读并发性 | 写性能可能降低 | getReadWriteLock |
信号量 | 限制资源并发访问数 | 限制同时访问某资源的线程数 | 控制资源并发访问 | 若不当使用,可能死锁 | getSemaphore |
可过期性信号量 | 各许可有过期时间的信号量 | 需许可有时间限制的场景 | 可自动释放超时许可 | 使用场景更复杂 | getPermitExpirableSemaphore |
闭锁 | 允许一线程等其他线程完成 | 确保某操作在其他操作完成后执行 | 确保任务执行顺序 | 不能重置 | getCountDownLatch |
✌ 1.1 可重入锁(Reentrant Lock)
✍ 作用
可重入锁是一种可以被同一个线程多次获取的锁。它可以避免线程死锁。
✍ 使用场景
- 当一个线程需要多次进入一个已经被其自己锁定的代码块时。
- 替代synchronized关键字提供更高的灵活性。
✍ 优缺点
🎷 优点
- 避免死锁。
- 提供了比synchronized更高的灵活性和功能。
🎷 缺点
- 更复杂,需要手动释放锁。
✍ 示例
// Spring Boot配置Redisson
@Configuration
public class RedissonConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
config.useSingleServer().setAddress("redis://" + host + ":" + port);
return Redisson.create(config);
}
}
// 使用可重入锁
@Service
public class SomeService {
@Autowired
private RedissonClient redissonClient;
public void someMethod() {
RLock lock = redissonClient.getLock("myLock");
try {
lock.lock();
// 执行业务代码
} finally {
lock.unlock();
}
}
}
✌ 1.2 公平锁(Fair Lock)
✍ 作用
公平锁是一种确保等待最长的线程首先获得锁的锁。
✍ 使用场景
- 当需要确保所有线程都有公平的机会访问资源时。
✍ 优缺点
🎷 优点
- 保证所有线程的公平访问。
🎷 缺点
- 性能低于非公平锁。
✍ 示例
@Service
public class FairService {
@Autowired
private RedissonClient redissonClient;
public void fairMethod() {
RLock fairLock = redissonClient.getFairLock("myFairLock");
try {
fairLock.lock();
// 执行业务代码
} finally {
fairLock.unlock();
}
}
}
✌ 1.3 联锁(MultiLock)
✍ 作用
当你需要所有锁都被同时获取才能进入临界区的情况下使用。
✍ 使用场景
- 当多个资源都需要被锁定以完成一个操作时。
✍ 优缺点
🎷 优点
- 可以确保所有必要的资源都被锁定。
🎷 缺点
- 更复杂,可能增加死锁的风险。
✍ 示例
@Service
public class MultiLockService {
@Autowired
private RedissonClient redissonClient;
public void multiLockMethod() {
RLock lock1 = redissonClient.getLock("lock1");
RLock lock2 = redissonClient.getLock("lock2");
RLock multiLock = redissonClient.getMultiLock(lock1, lock2);
try {
multiLock.lock();
// 执行业务代码
} finally {
multiLock.unlock();
}
}
}
✌ 1.4 红锁(RedLock)
✍ 作用
红锁是一种在多个Redis节点上实现的分布式锁算法。
✍ 使用场景
- 在Redis集群环境中确保资源的唯一访问。
✍ 优缺点
🎷 优点
- 提高了在Redis集群环境中锁的可靠性。
🎷 缺点
- 需要多个Redis实例来工作。
✍ 示例
@Service
public class RedLockService {
@Autowired
private RedissonClient redissonClient;
public void redLockMethod() {
RLock lock1 = redissonClient.getLock("lock1");
RLock lock2 = redissonClient.getLock("lock2");
RLock lock3 = redissonClient.getLock("lock3");
RedissonRedLock redLock = new RedissonRedLock(lock1, lock2, lock3);
try {
redLock.lock();
// 执行业务代码
} finally {
redLock.unlock();
}
}
}
✌ 1.5 读写锁(ReadWriteLock)
✍ 作用
读写锁允许多个线程同时读共享资源,但只允许一个线程写入。
✍ 使用场景
- 当需要多个线程同时读取,但只有一个线程修改资源时。
✍ 优缺点
🎷 优点
- 提高了读取的并发性。
🎷 缺点
- 写入的性能可能降低。
✍ 示例
@Service
public class ReadWriteLockService {
@Autowired
private RedissonClient redissonClient;
public void readMethod() {
RReadWriteLock rwlock = redissonClient.getReadWriteLock("myRWLock");
rwlock.readLock().lock();
try {
// 执行读取代码
} finally {
rwlock.readLock().unlock();
}
}
public void writeMethod() {
RReadWriteLock rwlock = redissonClient.getReadWriteLock("myRWLock");
rwlock.writeLock().lock();
try {
// 执行写入代码
} finally {
rwlock.writeLock().unlock();
}
}
}
✌ 1.6 信号量(Semaphore)
✍ 作用
信号量用于限制资源的并发访问数。
✍ 使用场景
- 当需要限制同时访问某资源的线程数量时。
✍ 优缺点
🎷 优点
- 可以有效控制资源的并发访问。
🎷 缺点
- 如果不正确使用,可能会导致死锁。
✍ 示例
@Service
public class SemaphoreService {
@Autowired
private RedissonClient redissonClient;
public void semaphoreMethod() {
RSemaphore semaphore = redissonClient.getSemaphore("mySemaphore");
try {
semaphore.acquire();
// 执行业务代码
} finally {
semaphore.release();
}
}
}
✌ 1.7 可过期性信号量(PermitExpirableSemaphore)
✍ 作用
与信号量类似,但每个许可都有一个过期时间。
✍ 使用场景
- 当需要许可有时间限制的场景。
✍ 优缺点
🎷 优点
- 可以自动释放超时的许可。
🎷 缺点
- 更复杂的使用场景。
✍ 示例
@Service
public class ExpirableSemaphoreService {
@Autowired
private RedissonClient redissonClient;
public void expirableSemaphoreMethod() throws InterruptedException {
RPermitExpirableSemaphore semaphore = redissonClient.getPermitExpirableSemaphore("myExpirableSemaphore");
String permitId = semaphore.acquire();
try {
// 执行业务代码
} finally {
semaphore.release(permitId);
}
}
}
✌ 1.8 闭锁(CountDownLatch)
✍ 作用
允许一个或多个线程等待其他线程完成操作。
✍ 使用场景
- 当需要确保某些操作在其他操作完成后再执行。
✍ 优缺点
🎷 优点
- 可以确保任务的执行顺序。
🎷 缺点
- 不能被重置。
✍ 示例
@Service
public class CountDownLatchService {
@Autowired
private RedissonClient redissonClient;
public void latchMethod() throws InterruptedException {
RCountDownLatch latch = redissonClient.getCountDownLatch("myLatch");
latch.trySetCount(3);
// In worker threads
latch.countDown();
// In main thread
latch.await();
}
}