0
# Locks and Synchronization
1
2
Redisson provides distributed implementations of Java's concurrency primitives, allowing coordination and synchronization across multiple JVM instances using Redis as the coordination backend.
3
4
## Capabilities
5
6
### Distributed Locks
7
8
Distributed locking mechanisms for mutual exclusion across multiple processes and servers.
9
10
```java { .api }
11
/**
12
* Get a distributed reentrant lock
13
* @param name - unique name of the lock
14
* @return RLock instance
15
*/
16
public RLock getLock(String name);
17
public RLock getLock(CommonOptions options);
18
19
/**
20
* Get a spin lock that uses spinning instead of blocking
21
* @param name - unique name of the spin lock
22
* @return RLock instance configured for spinning
23
*/
24
public RLock getSpinLock(String name);
25
public RLock getSpinLock(String name, LockOptions.BackOff backOff);
26
27
/**
28
* Get a fair lock ensuring FIFO order of lock acquisition
29
* @param name - unique name of the fair lock
30
* @return RLock instance with fair ordering
31
*/
32
public RLock getFairLock(String name);
33
public RLock getFairLock(CommonOptions options);
34
35
/**
36
* Get a read-write lock for reader-writer synchronization
37
* @param name - unique name of the read-write lock
38
* @return RReadWriteLock instance with separate read and write locks
39
*/
40
public RReadWriteLock getReadWriteLock(String name);
41
public RReadWriteLock getReadWriteLock(CommonOptions options);
42
43
/**
44
* Get a fenced lock with fencing tokens for ordering
45
* @param name - unique name of the fenced lock
46
* @return RFencedLock instance with fencing token support
47
*/
48
public RFencedLock getFencedLock(String name);
49
public RFencedLock getFencedLock(CommonOptions options);
50
51
/**
52
* Create a multi-lock that acquires multiple locks atomically
53
* @param locks - array of locks to acquire together
54
* @return RLock instance representing the multi-lock
55
*/
56
public RLock getMultiLock(RLock... locks);
57
public RLock getMultiLock(String group, Collection<Object> values);
58
```
59
60
**Lock Interfaces:**
61
62
```java { .api }
63
// Main distributed lock interface
64
public interface RLock extends Lock, RLockAsync {
65
void lock();
66
void lock(long leaseTime, TimeUnit unit);
67
void lockInterruptibly() throws InterruptedException;
68
void lockInterruptibly(long leaseTime, TimeUnit unit) throws InterruptedException;
69
70
boolean tryLock();
71
boolean tryLock(long waitTime, TimeUnit unit) throws InterruptedException;
72
boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException;
73
74
void unlock();
75
Condition newCondition();
76
77
// Redisson-specific methods
78
void forceUnlock();
79
boolean isLocked();
80
boolean isHeldByThread(long threadId);
81
boolean isHeldByCurrentThread();
82
int getHoldCount();
83
long remainTimeToLive();
84
String getName();
85
}
86
87
// Read-write lock interface
88
public interface RReadWriteLock extends ReadWriteLock {
89
RLock readLock();
90
RLock writeLock();
91
String getName();
92
}
93
94
// Fenced lock with fencing tokens
95
public interface RFencedLock extends RLock {
96
Long lockAndGetToken();
97
Long lockAndGetToken(long leaseTime, TimeUnit unit);
98
boolean tryLockAndGetToken();
99
boolean tryLockAndGetToken(long waitTime, TimeUnit unit) throws InterruptedException;
100
boolean tryLockAndGetToken(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException;
101
102
Long getToken();
103
}
104
```
105
106
**Usage Examples:**
107
108
```java
109
import org.redisson.api.*;
110
import java.util.concurrent.TimeUnit;
111
112
// Basic lock usage
113
RLock lock = redisson.getLock("myLock");
114
lock.lock();
115
try {
116
// Critical section - only one thread can execute this across all instances
117
System.out.println("Protected code execution");
118
} finally {
119
lock.unlock(); // Always unlock in finally block
120
}
121
122
// Lock with automatic expiration (lease time)
123
RLock lockWithLease = redisson.getLock("timedLock");
124
lockWithLease.lock(10, TimeUnit.SECONDS); // Auto-unlock after 10 seconds
125
try {
126
// Protected code with timeout
127
} finally {
128
if (lockWithLease.isHeldByCurrentThread()) {
129
lockWithLease.unlock();
130
}
131
}
132
133
// Try lock with timeout
134
RLock tryLock = redisson.getLock("conditionalLock");
135
if (tryLock.tryLock(5, TimeUnit.SECONDS)) {
136
try {
137
// Got the lock within 5 seconds
138
} finally {
139
tryLock.unlock();
140
}
141
} else {
142
System.out.println("Could not acquire lock within timeout");
143
}
144
145
// Fair lock for FIFO ordering
146
RLock fairLock = redisson.getFairLock("fairQueue");
147
fairLock.lock();
148
try {
149
// Threads acquire this lock in the order they requested it
150
} finally {
151
fairLock.unlock();
152
}
153
154
// Read-write lock for reader-writer scenarios
155
RReadWriteLock rwLock = redisson.getReadWriteLock("dataLock");
156
157
// Reader threads
158
RLock readLock = rwLock.readLock();
159
readLock.lock();
160
try {
161
// Multiple readers can access simultaneously
162
String data = readSharedData();
163
} finally {
164
readLock.unlock();
165
}
166
167
// Writer thread
168
RLock writeLock = rwLock.writeLock();
169
writeLock.lock();
170
try {
171
// Exclusive access for writing
172
writeSharedData("new data");
173
} finally {
174
writeLock.unlock();
175
}
176
177
// Multi-lock for atomic operations across multiple resources
178
RLock lock1 = redisson.getLock("resource1");
179
RLock lock2 = redisson.getLock("resource2");
180
RLock multiLock = redisson.getMultiLock(lock1, lock2);
181
multiLock.lock();
182
try {
183
// Both locks acquired atomically
184
} finally {
185
multiLock.unlock();
186
}
187
188
// Fenced lock with tokens
189
RFencedLock fencedLock = redisson.getFencedLock("fencedResource");
190
Long token = fencedLock.lockAndGetToken();
191
try {
192
// Use token for ordering operations
193
processWithToken(token);
194
} finally {
195
fencedLock.unlock();
196
}
197
```
198
199
### Semaphores
200
201
Distributed semaphores for controlling access to resources with limited capacity.
202
203
```java { .api }
204
/**
205
* Get a distributed semaphore
206
* @param name - unique name of the semaphore
207
* @return RSemaphore instance
208
*/
209
public RSemaphore getSemaphore(String name);
210
public RSemaphore getSemaphore(CommonOptions options);
211
212
/**
213
* Get a permit-expirable semaphore where permits can expire
214
* @param name - unique name of the permit expirable semaphore
215
* @return RPermitExpirableSemaphore instance
216
*/
217
public RPermitExpirableSemaphore getPermitExpirableSemaphore(String name);
218
public RPermitExpirableSemaphore getPermitExpirableSemaphore(CommonOptions options);
219
```
220
221
**Semaphore Interfaces:**
222
223
```java { .api }
224
// Standard distributed semaphore
225
public interface RSemaphore extends RObject, RExpirable {
226
void acquire() throws InterruptedException;
227
void acquire(int permits) throws InterruptedException;
228
void acquireUninterruptibly();
229
void acquireUninterruptibly(int permits);
230
231
boolean tryAcquire();
232
boolean tryAcquire(int permits);
233
boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException;
234
boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException;
235
236
void release();
237
void release(int permits);
238
239
int availablePermits();
240
int drainPermits();
241
boolean hasQueuedThreads();
242
int getQueueLength();
243
244
boolean trySetPermits(int permits);
245
void addPermits(int permits);
246
boolean updateLeaseTime(String permitId, long leaseTime, TimeUnit unit);
247
}
248
249
// Semaphore with expirable permits
250
public interface RPermitExpirableSemaphore extends RObject, RExpirable {
251
String acquire() throws InterruptedException;
252
List<String> acquire(int permits) throws InterruptedException;
253
String acquire(long leaseTime, TimeUnit unit) throws InterruptedException;
254
List<String> acquire(int permits, long leaseTime, TimeUnit unit) throws InterruptedException;
255
256
String tryAcquire();
257
List<String> tryAcquire(int permits);
258
String tryAcquire(long waitTime, TimeUnit unit) throws InterruptedException;
259
String tryAcquire(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException;
260
List<String> tryAcquire(int permits, long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException;
261
262
boolean tryRelease(String permitId);
263
int tryRelease(Collection<String> permitIds);
264
void release(String permitId);
265
void release(Collection<String> permitIds);
266
267
int availablePermits();
268
boolean trySetPermits(int permits);
269
void addPermits(int permits);
270
boolean updateLeaseTime(String permitId, long leaseTime, TimeUnit unit);
271
}
272
```
273
274
**Usage Examples:**
275
276
```java
277
// Basic semaphore usage
278
RSemaphore semaphore = redisson.getSemaphore("connectionPool");
279
semaphore.trySetPermits(10); // Set maximum permits to 10
280
281
// Acquire permit
282
semaphore.acquire(); // Blocks until permit available
283
try {
284
// Use limited resource (e.g., database connection)
285
processWithLimitedResource();
286
} finally {
287
semaphore.release(); // Return permit
288
}
289
290
// Try acquire with timeout
291
if (semaphore.tryAcquire(5, TimeUnit.SECONDS)) {
292
try {
293
// Got permit within 5 seconds
294
} finally {
295
semaphore.release();
296
}
297
} else {
298
System.out.println("No permits available");
299
}
300
301
// Acquire multiple permits
302
RSemaphore batchSemaphore = redisson.getSemaphore("batchProcessor");
303
batchSemaphore.acquire(3); // Acquire 3 permits for batch operation
304
try {
305
// Process batch requiring 3 resources
306
} finally {
307
batchSemaphore.release(3);
308
}
309
310
// Expirable permits semaphore
311
RPermitExpirableSemaphore expirableSemaphore = redisson.getPermitExpirableSemaphore("tempResources");
312
String permitId = expirableSemaphore.acquire(30, TimeUnit.SECONDS); // Permit expires in 30 seconds
313
if (permitId != null) {
314
try {
315
// Use resource with automatic cleanup
316
} finally {
317
expirableSemaphore.release(permitId);
318
}
319
}
320
321
// Multiple permits with expiration
322
List<String> permitIds = expirableSemaphore.acquire(3, 60, TimeUnit.SECONDS);
323
try {
324
// Use 3 resources that expire in 60 seconds
325
} finally {
326
expirableSemaphore.release(permitIds);
327
}
328
```
329
330
### CountDown Latches
331
332
Distributed countdown latches for coordinating thread execution across processes.
333
334
```java { .api }
335
/**
336
* Get a distributed countdown latch
337
* @param name - unique name of the countdown latch
338
* @return RCountDownLatch instance
339
*/
340
public RCountDownLatch getCountDownLatch(String name);
341
public RCountDownLatch getCountDownLatch(CommonOptions options);
342
```
343
344
**CountDown Latch Interface:**
345
346
```java { .api }
347
public interface RCountDownLatch extends RObject, RExpirable {
348
void await() throws InterruptedException;
349
boolean await(long timeout, TimeUnit unit) throws InterruptedException;
350
351
void countDown();
352
long getCount();
353
boolean trySetCount(long count);
354
}
355
```
356
357
**Usage Examples:**
358
359
```java
360
// Coordination example: wait for all workers to complete initialization
361
RCountDownLatch initLatch = redisson.getCountDownLatch("initLatch");
362
int workerCount = 5;
363
initLatch.trySetCount(workerCount);
364
365
// Worker threads
366
// Each worker does this after initialization:
367
// initLatch.countDown();
368
369
// Main thread waits for all workers
370
initLatch.await(); // Blocks until count reaches 0
371
System.out.println("All workers initialized, starting main processing");
372
373
// With timeout
374
RCountDownLatch processLatch = redisson.getCountDownLatch("processLatch");
375
processLatch.trySetCount(3);
376
377
if (processLatch.await(30, TimeUnit.SECONDS)) {
378
System.out.println("All processes completed within timeout");
379
} else {
380
System.out.println("Timeout waiting for processes");
381
}
382
383
// Racing start example
384
RCountDownLatch startLatch = redisson.getCountDownLatch("raceStart");
385
startLatch.trySetCount(1);
386
387
// All participants wait
388
startLatch.await();
389
System.out.println("Race started!");
390
391
// Coordinator starts the race
392
// startLatch.countDown(); // This releases all waiting threads
393
```
394
395
### Advanced Synchronization
396
397
Additional synchronization primitives for specialized use cases.
398
399
```java { .api }
400
/**
401
* Get atomic long for distributed atomic operations
402
* @param name - unique name of the atomic long
403
* @return RAtomicLong instance
404
*/
405
public RAtomicLong getAtomicLong(String name);
406
407
/**
408
* Get atomic double for distributed atomic operations
409
* @param name - unique name of the atomic double
410
* @return RAtomicDouble instance
411
*/
412
public RAtomicDouble getAtomicDouble(String name);
413
414
/**
415
* Get long adder for high-throughput distributed counting
416
* @param name - unique name of the long adder
417
* @return RLongAdder instance
418
*/
419
public RLongAdder getLongAdder(String name);
420
421
/**
422
* Get double adder for high-throughput distributed summing
423
* @param name - unique name of the double adder
424
* @return RDoubleAdder instance
425
*/
426
public RDoubleAdder getDoubleAdder(String name);
427
```
428
429
**Atomic Interfaces:**
430
431
```java { .api }
432
// Distributed atomic long
433
public interface RAtomicLong extends RObject, RExpirable {
434
long get();
435
void set(long newValue);
436
long getAndSet(long newValue);
437
438
boolean compareAndSet(long expect, long update);
439
long addAndGet(long delta);
440
long getAndAdd(long delta);
441
long incrementAndGet();
442
long getAndIncrement();
443
long decrementAndGet();
444
long getAndDecrement();
445
446
long updateAndGet(LongUnaryOperator updateFunction);
447
long getAndUpdate(LongUnaryOperator updateFunction);
448
long accumulateAndGet(long x, LongBinaryOperator accumulatorFunction);
449
long getAndAccumulate(long x, LongBinaryOperator accumulatorFunction);
450
}
451
452
// Distributed atomic double
453
public interface RAtomicDouble extends RObject, RExpirable {
454
double get();
455
void set(double newValue);
456
double getAndSet(double newValue);
457
458
boolean compareAndSet(double expect, double update);
459
double addAndGet(double delta);
460
double getAndAdd(double delta);
461
}
462
463
// High-performance distributed counter
464
public interface RLongAdder extends RObject, RExpirable {
465
void add(long x);
466
void increment();
467
void decrement();
468
long sum();
469
void reset();
470
long sumThenReset();
471
}
472
```
473
474
**Usage Examples:**
475
476
```java
477
// Distributed counter
478
RAtomicLong counter = redisson.getAtomicLong("globalCounter");
479
counter.set(0);
480
481
// Atomic operations across multiple JVMs
482
long newValue = counter.incrementAndGet(); // Thread-safe increment
483
long previousValue = counter.getAndAdd(5); // Add 5 and return previous value
484
485
// Compare and swap
486
long current = counter.get();
487
boolean success = counter.compareAndSet(current, current * 2);
488
489
// High-performance counting with RLongAdder
490
RLongAdder adder = redisson.getLongAdder("highThroughputCounter");
491
// Multiple threads can call this concurrently with high performance
492
adder.increment();
493
adder.add(10);
494
495
// Get sum when needed (more expensive operation)
496
long total = adder.sum();
497
System.out.println("Total count: " + total);
498
```
499
500
## Lock Options and Configuration
501
502
```java { .api }
503
// Common options for most synchronization primitives
504
public class CommonOptions extends PlainOptions {
505
private String name;
506
private Codec codec;
507
508
public CommonOptions name(String name);
509
public CommonOptions codec(Codec codec);
510
}
511
512
// Lock-specific options
513
public class LockOptions {
514
public enum BackOff {
515
EXPONENTIAL_BACKOFF,
516
LINEAR_BACKOFF,
517
CONSTANT_BACKOFF
518
}
519
520
public static class BackOffPolicy {
521
private BackOff backOff;
522
private long initialDelay;
523
private long maxDelay;
524
private double multiplier;
525
526
// Configuration methods
527
public BackOffPolicy backOff(BackOff backOff);
528
public BackOffPolicy initialDelay(long initialDelay, TimeUnit timeUnit);
529
public BackOffPolicy maxDelay(long maxDelay, TimeUnit timeUnit);
530
public BackOffPolicy multiplier(double multiplier);
531
}
532
}
533
534
// Transaction options for coordinated operations
535
public class TransactionOptions {
536
private long responseTimeout = 3000;
537
private int retryAttempts = 3;
538
private long retryInterval = 1500;
539
private SyncMode syncMode = SyncMode.ACK;
540
541
public TransactionOptions responseTimeout(long responseTimeout, TimeUnit unit);
542
public TransactionOptions retryAttempts(int retryAttempts);
543
public TransactionOptions retryInterval(long retryInterval, TimeUnit unit);
544
public TransactionOptions syncMode(SyncMode syncMode);
545
}
546
```