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