使用
1、引入依赖:
<!--以后使用redis作为所有分布式锁,分布式对象等功能框架-->
<!-- https://mvnrepository.com/artifact/org.redisson/redisson -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.12.0</version>
</dependency>
2、程序化配置方法
@Configuration
public class MyRedisConfig {
@Bean(destroyMethod="shutdown")
public RedissonClient redisson() throws IOException {
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("li199852");
RedissonClient redisson = Redisson.create(config);
return redisson;
}
}
以后操作都是使用redissonClient操作:
@Autowired
RedissonClient redissonClient;
4、可重入锁(Reentrant Lock)
他的使用和java的Lack锁差不多:
@GetMapping("/hello")
@ResponseBody
public String hello(){
//1.获取一把锁,只要锁的名字一样,就是同一把锁
RLock lock = redisson.getLock("my-lock");
//2.加锁
lock.lock();//原理是阻塞式等待,默认加的锁都是30s的时间
/*
问题:lock.lock(10, TimeUnit.SECONDS)锁到期之后,不会自动续期。
1、如果我们传递了锁的超时时间,就发送给redis执行脚本,进行占锁,默认超时就是我们指定的时间
2、如果我们未指定锁的超时时间,就使用30*1000【lockWatchdogTimeout看门狗的默认时间】;
只要占锁成功,就会启动一个定时任务【重新给锁设置过期时间,新的过期时间就是看门狗的默认时间】
initernallockLeaseTime【看门狗时间】 / 3 ,也就是10秒调用一次重置时间方法
*/
/*
优点:
1)、锁的自动续期,如果业务超长,运行期间自动给锁锁上新的30s。不用担心业务时间长,锁自动被删掉
2)、加锁的业务自动运行完成,就不会给当前锁续期,即使不手动解锁,锁默认会在30s以后自动删除
*/
try {
System.out.println("我拿到了锁"+Thread.currentThread().getId());
Thread.sleep(20000);
} catch (Exception e) {
e.printStackTrace();
} finally {
//3.解锁,假设解锁代码没有运行,redisson会不会出现死锁:不会,锁默认会在30s以后自动删除
System.out.println("我释放了锁"+Thread.currentThread().getId());
lock.unlock();
}
return "hello";
}
推荐使用:
可以省掉续期的操作,如果业务30秒还执行不完,就要改造业务了;
lock.lock(30, TimeUnit.SECONDS);//锁到期之后,不会自动续期,需要手动解锁。
5、读写锁(ReadWriteLock)
//保证一定能读到最新数据,修改期间,写锁是一个排他锁(互斥锁)。
//读锁是一个共享锁写锁没释放读就必须等待
/*
先读 + 后读:相当于无锁,并发读,只会在redis中记录好,所有当前的读锁。他们都会同时加锁成功
先写 + 后读:等待写锁释放
先写 + 后写:阻塞方式
先读 + 后写:有读锁。写也需要等待。
只要有写的存在,都必须等待
*/
@RequestMapping("/write")
@ResponseBody
public String writeString() {
RReadWriteLock readWriteLock = redisson.getReadWriteLock("readWriteLock");
RLock wLock = readWriteLock.writeLock();
String s = "";
try {
wLock.lock(20, TimeUnit.SECONDS);
s = UUID.randomUUID().toString();
Thread.sleep(10000);
redisTemplate.opsForValue().set("s", s);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
wLock.unlock();
}
return s;
}
@RequestMapping("/read")
@ResponseBody
public String readString() {
RReadWriteLock readWriteLock = redisson.getReadWriteLock("readWriteLock");
RLock rLock = readWriteLock.readLock();
String s = "";
try {
rLock.lock(20,TimeUnit.SECONDS);
s = redisTemplate.opsForValue().get("s");
}finally {
rLock.unlock();
}
return s;
}
6、信号量(Semaphore)(还有一个可过期性信号量(PermitExpirableSemaphore))
/**
* 信号量(Semaphore)
* 默认是获取的
* @return
*/
@RequestMapping("/goOneCar")
@ResponseBody
public String goOneCar(){
RSemaphore semaphore = redisson.getSemaphore("semaphore-Lock");
semaphore.release();//释放当前一个车位
return "出去一辆车";
}
@RequestMapping("/comeOneCar")
@ResponseBody
public String comeOneCar() throws InterruptedException {
RSemaphore semaphore = redisson.getSemaphore("semaphore-Lock");
// semaphore.acquire();//获取当前一个车位
semaphore.tryAcquire(10);//尝试获取当前十个车位,没有或不够就算了
return "进来一辆车";
}
7、闭锁(CountDownLatch)
/**
* 闭锁:CountDownLatch
* 五个人都走出教室了在锁门,
*/
//锁门
@RequestMapping("/closeDoor")
@ResponseBody
public String closeDoor() throws InterruptedException {
RCountDownLatch countDownLatch = redisson.getCountDownLatch("countDownLatch-Lack");
countDownLatch.trySetCount(5);
countDownLatch.await();
return "门锁了";
}
//出去
@RequestMapping("/goOut")
@ResponseBody
public String goOut(Long id){
RCountDownLatch countDownLatch = redisson.getCountDownLatch("countDownLatch-Lack");
countDownLatch.countDown();
return id+"出去了";
}
其他可以参考redis官网,链接:https://github.com/redisson/redisson/wiki/8.-%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E5%92%8C%E5%90%8C%E6%AD%A5%E5%99%A8