使用
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