or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

collections.mdconfiguration.mddata-structures.mdindex.mdmessaging.mdreactive-async.mdsynchronization.md

synchronization.mddocs/

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

```