Fair Lock
The Redisson distributed reentrant fair lock based on Redis is also a RLock
object that implements the java.util.concurrent.locks.Lock
interface. It also provides asynchronous (Async), reflective (Reactive) and RxJava2 standard interfaces. It ensures that when multiple Redisson client threads request locks at the same time, priority will be given to the thread that made the request first. All request threads will be queued in a queue. When a thread goes down, Redisson will wait for 5 seconds before continuing to the next thread. That is to say, if the previous 5 threads are waiting, then the following threads will wait. At least 25 seconds.
RLock fairLock = redisson.getFairLock("anyLock"); //The most common usage fairLock.lock(); // Automatically unlock after 10 seconds // No need to call the unlock method to manually unlock fairLock.lock(10, TimeUnit.SECONDS); //Try to lock, wait up to 100 seconds, and automatically unlock 10 seconds after locking boolean res = fairLock.tryLock(100, 10, TimeUnit.SECONDS); fairLock.unlock();
Interlock (MultiLock)
The Redisson distributed interlock RedissonMultiLock
object based on Redis can associate multiple RLock
objects into an interlock. Each RLock
object instance can come from for different Redisson instances.
RLock lock1 = redissonInstance1.getLock("lock1"); RLock lock2 = redissonInstance2.getLock("lock2"); RLock lock3 = redissonInstance3.getLock("lock3"); RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3); // Lock simultaneously: lock1 lock2 lock3 // Success is considered successful if all locks are successfully locked. lock.lock(); ... lock.unlock();
RedLock
The Redisson red lock RedissonRedLock
object based on Redis implements the locking algorithm introduced by Redlock. This object can also be used to associate multiple RLock
objects into a red lock. Each RLock
object instance can come from a different Redisson instance.
RLock lock1 = redissonInstance1.getLock("lock1"); RLock lock2 = redissonInstance2.getLock("lock2"); RLock lock3 = redissonInstance3.getLock("lock3"); RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3); // Lock simultaneously: lock1 lock2 lock3 // The red lock is considered successful if it is successfully locked on most nodes. lock.lock(); ... lock.unlock();
Read-write lock (ReadWriteLock)
The Redisson distributed reentrant read-write lock based on Redis RReadWriteLock
Java object implements the java.util.concurrent.locks.ReadWriteLock
interface. Both read locks and write locks inherit the RLock interface.
Distributed reentrant read-write locks allow multiple read locks and one write lock to be locked at the same time.
RReadWriteLock rwlock = redisson.getReadWriteLock("anyRWLock"); //The most common usage rwlock.readLock().lock(); // or rwlock.writeLock().lock(); // Automatically unlock after 10 seconds // No need to call the unlock method to manually unlock rwlock.readLock().lock(10, TimeUnit.SECONDS); // or rwlock.writeLock().lock(10, TimeUnit.SECONDS); //Try to lock, wait up to 100 seconds, and automatically unlock 10 seconds after locking boolean res = rwlock.readLock().tryLock(100, 10, TimeUnit.SECONDS); // or boolean res = rwlock.writeLock().tryLock(100, 10, TimeUnit.SECONDS); ... lock.unlock();
Add StockController method:
@GetMapping("test/read") public String testRead(){<!-- --> String msg = stockService.testRead(); return "Test read"; } @GetMapping("test/write") public String testWrite(){<!-- --> String msg = stockService.testWrite(); return "Test writing"; }
Add StockService method:
public String testRead() {<!-- --> RReadWriteLock rwLock = this.redissonClient.getReadWriteLock("rwLock"); rwLock.readLock().lock(10, TimeUnit.SECONDS); System.out.println("Test read lock..."); // rwLock.readLock().unlock(); return null; } public String testWrite() {<!-- --> RReadWriteLock rwLock = this.redissonClient.getReadWriteLock("rwLock"); rwLock.writeLock().lock(10, TimeUnit.SECONDS); System.out.println("Test write lock..."); // rwLock.writeLock().unlock(); return null; }
Open two browser windows to test:
- Simultaneous access writing: After one writing is completed, wait for a while (about 10s), and the other writing starts
- Simultaneous access to read: no need to wait
- Write first and then read: Read and wait (about 10s) for writing to complete.
- Read first and then write: write and wait (about 10s) for reading to complete.
Semaphore
Redisson’s distributed semaphore (Semaphore) Java object RSemaphore
based on Redis adopts an interface and usage similar to java.util.concurrent.Semaphore
. It also provides asynchronous (Async), reflective (Reactive) and RxJava2 standard interfaces.
RSemaphore semaphore = redisson.getSemaphore("semaphore"); semaphore.trySetPermits(3); semaphore.acquire(); semaphore.release();
Add method to StockController:
@GetMapping("test/semaphore") public String testSemaphore(){<!-- --> this.stockService.testSemaphore(); return "Test semaphore"; }
Add method in StockService:
public void testSemaphore() {<!-- --> RSemaphore semaphore = this.redissonClient.getSemaphore("semaphore"); semaphore.trySetPermits(3); try {<!-- --> semaphore.acquire(); TimeUnit.SECONDS.sleep(5); System.out.println(System.currentTimeMillis()); semaphore.release(); } catch (InterruptedException e) {<!-- --> e.printStackTrace(); } }
Add test case: concurrency 10 times, loop once
Console effect:
Console 1: 1606960790234 1606960800337 1606960800443 1606960805248 Console 2: 1606960790328 1606960795332 1606960800245 Console 3: 1606960790433 1606960795238 1606960795437
It can be seen from this:
3 requests came in during 1606960790 seconds: 1 for each console
There were 3 requests coming in during 1606960795 seconds: 1 request from console 2 and 2 requests from console 3.
3 requests came in during 1606960800 seconds: 2 requests from console 1 and 1 request from console 2.
1 request came in in 1606960805 seconds: 1 request from console 1
Latch (CountDownLatch)
The Redisson distributed locking (CountDownLatch) Java object RCountDownLatch
based on Redisson adopts an interface and usage similar to java.util.concurrent.CountDownLatch
.
RCountDownLatch latch = redisson.getCountDownLatch("anyCountDownLatch"); latch.trySetCount(1); latch.await(); // In other threads or other JVMs RCountDownLatch latch = redisson.getCountDownLatch("anyCountDownLatch"); latch.countDown();
Two methods are needed: one waiting and one counting countDown
Add a test method to StockController:
@GetMapping("test/latch") public String testLatch(){<!-- --> this.stockService.testLatch(); return "The squad leader locked the door..."; } @GetMapping("test/countdown") public String testCountDown(){<!-- --> this.stockService.testCountDown(); return "A classmate came out"; }
Add a test method to StockService:
public void testLatch() {<!-- --> RCountDownLatch latch = this.redissonClient.getCountDownLatch("latch"); latch.trySetCount(6); try {<!-- --> latch.await(); } catch (InterruptedException e) {<!-- --> e.printStackTrace(); } } public void testCountDown() {<!-- --> RCountDownLatch latch = this.redissonClient.getCountDownLatch("latch"); latch.trySetCount(6); latch.countDown(); }
Restart the test and open two pages: the first request will not be executed until the second request is executed 6 times.