0
# Distributed Locking
1
2
Distributed locking capabilities for coordinating access to shared resources across multiple processes and JVMs. Provides various locking mechanisms including mutexes, read-write locks, and semaphores with support for revocation and automatic cleanup.
3
4
## Capabilities
5
6
### InterProcessLock Interface
7
8
Base interface for all distributed locks providing consistent acquire/release semantics.
9
10
```java { .api }
11
/**
12
* Base interface for distributed locks that work across processes
13
*/
14
public interface InterProcessLock {
15
/**
16
* Acquire the lock, blocking until available
17
* @throws Exception if the lock cannot be acquired
18
*/
19
void acquire() throws Exception;
20
21
/**
22
* Acquire the lock within the given time period
23
* @param time maximum time to wait for the lock
24
* @param unit time unit of the time argument
25
* @return true if the lock was acquired, false otherwise
26
* @throws Exception if an error occurs during acquisition
27
*/
28
boolean acquire(long time, TimeUnit unit) throws Exception;
29
30
/**
31
* Release the lock
32
* @throws Exception if the lock cannot be released
33
*/
34
void release() throws Exception;
35
}
36
```
37
38
### InterProcessMutex
39
40
Re-entrant mutex implementation that works across JVMs. The same thread can acquire the lock multiple times.
41
42
```java { .api }
43
/**
44
* Re-entrant mutex that works across JVMs using ZooKeeper
45
*/
46
public class InterProcessMutex implements InterProcessLock {
47
/**
48
* Create a new InterProcessMutex
49
* @param client the curator client
50
* @param path the path to use for the lock
51
*/
52
public InterProcessMutex(CuratorFramework client, String path);
53
54
/**
55
* Acquire the lock, blocking until available
56
*/
57
public void acquire() throws Exception;
58
59
/**
60
* Acquire the lock within the given time period
61
* @param time maximum time to wait
62
* @param unit time unit
63
* @return true if acquired, false if timed out
64
*/
65
public boolean acquire(long time, TimeUnit unit) throws Exception;
66
67
/**
68
* Release the lock
69
*/
70
public void release() throws Exception;
71
72
/**
73
* Check if this mutex is acquired by the current thread
74
* @return true if acquired by current thread
75
*/
76
public boolean isAcquiredInThisProcess();
77
}
78
```
79
80
**Usage Example:**
81
82
```java
83
import org.apache.curator.framework.CuratorFramework;
84
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
85
86
CuratorFramework client = // ... initialize client
87
InterProcessMutex lock = new InterProcessMutex(client, "/app/locks/resource");
88
89
try {
90
if (lock.acquire(10, TimeUnit.SECONDS)) {
91
// Critical section - only one process can execute this
92
System.out.println("Processing shared resource");
93
// ... do work
94
} else {
95
System.out.println("Could not acquire lock within 10 seconds");
96
}
97
} finally {
98
lock.release(); // Always release in finally block
99
}
100
```
101
102
### InterProcessSemaphoreMutex
103
104
Non-reentrant mutex implementation. Unlike InterProcessMutex, the same thread cannot acquire this lock multiple times.
105
106
```java { .api }
107
/**
108
* Non-reentrant mutex that works across JVMs
109
*/
110
public class InterProcessSemaphoreMutex implements InterProcessLock {
111
/**
112
* Create a new InterProcessSemaphoreMutex
113
* @param client the curator client
114
* @param path the path to use for the lock
115
*/
116
public InterProcessSemaphoreMutex(CuratorFramework client, String path);
117
118
public void acquire() throws Exception;
119
public boolean acquire(long time, TimeUnit unit) throws Exception;
120
public void release() throws Exception;
121
}
122
```
123
124
### InterProcessReadWriteLock
125
126
Read-write lock implementation allowing multiple readers or one writer across JVMs.
127
128
```java { .api }
129
/**
130
* Re-entrant read/write mutex that works across JVMs
131
*/
132
public class InterProcessReadWriteLock {
133
/**
134
* Create a new InterProcessReadWriteLock
135
* @param client the curator client
136
* @param lockPath the path to use for the lock
137
*/
138
public InterProcessReadWriteLock(CuratorFramework client, String lockPath);
139
140
/**
141
* Get the read lock portion of this lock
142
* @return read lock instance
143
*/
144
public InterProcessLock readLock();
145
146
/**
147
* Get the write lock portion of this lock
148
* @return write lock instance
149
*/
150
public InterProcessLock writeLock();
151
152
/**
153
* Nested class for read lock component
154
*/
155
public static class ReadLock implements InterProcessLock {
156
public void acquire() throws Exception;
157
public boolean acquire(long time, TimeUnit unit) throws Exception;
158
public void release() throws Exception;
159
}
160
161
/**
162
* Nested class for write lock component
163
*/
164
public static class WriteLock implements InterProcessLock {
165
public void acquire() throws Exception;
166
public boolean acquire(long time, TimeUnit unit) throws Exception;
167
public void release() throws Exception;
168
}
169
}
170
```
171
172
**Usage Example:**
173
174
```java
175
InterProcessReadWriteLock rwLock = new InterProcessReadWriteLock(client, "/app/locks/data");
176
InterProcessLock readLock = rwLock.readLock();
177
InterProcessLock writeLock = rwLock.writeLock();
178
179
// Multiple readers can acquire simultaneously
180
readLock.acquire();
181
try {
182
// Read shared data
183
System.out.println("Reading data...");
184
} finally {
185
readLock.release();
186
}
187
188
// Only one writer can acquire (and no readers)
189
writeLock.acquire();
190
try {
191
// Write shared data
192
System.out.println("Writing data...");
193
} finally {
194
writeLock.release();
195
}
196
```
197
198
### InterProcessMultiLock
199
200
Container for managing multiple locks as a single entity. All locks must be acquired for the multi-lock to be considered acquired.
201
202
```java { .api }
203
/**
204
* Container holding multiple locks and treating them as a single lock
205
*/
206
public class InterProcessMultiLock implements InterProcessLock {
207
/**
208
* Create a new InterProcessMultiLock
209
* @param locks list of locks to manage together
210
*/
211
public InterProcessMultiLock(List<InterProcessLock> locks);
212
213
/**
214
* Acquire all locks in the multi-lock
215
*/
216
public void acquire() throws Exception;
217
218
/**
219
* Acquire all locks within the given time period
220
*/
221
public boolean acquire(long time, TimeUnit unit) throws Exception;
222
223
/**
224
* Release all locks in the multi-lock
225
*/
226
public void release() throws Exception;
227
}
228
```
229
230
### InterProcessSemaphoreV2
231
232
Counting semaphore that works across JVMs, allowing a specified number of processes to acquire the semaphore.
233
234
```java { .api }
235
/**
236
* Counting semaphore that works across JVMs
237
*/
238
public class InterProcessSemaphoreV2 {
239
/**
240
* Create a new InterProcessSemaphoreV2
241
* @param client the curator client
242
* @param mutexPath the path to use for the semaphore
243
* @param maxLeases maximum number of simultaneous leases
244
*/
245
public InterProcessSemaphoreV2(CuratorFramework client, String mutexPath, int maxLeases);
246
247
/**
248
* Acquire a lease from the semaphore
249
* @return acquired lease, or null if not available
250
*/
251
public Lease acquire() throws Exception;
252
253
/**
254
* Acquire a lease within the given time period
255
*/
256
public Lease acquire(long time, TimeUnit unit) throws Exception;
257
258
/**
259
* Acquire multiple leases
260
* @param qty number of leases to acquire
261
* @return collection of acquired leases
262
*/
263
public Collection<Lease> acquire(int qty) throws Exception;
264
265
/**
266
* Get current available leases
267
* @return number of available leases
268
*/
269
public int availablePermits() throws Exception;
270
271
/**
272
* Return a lease to the semaphore
273
* @param lease the lease to return
274
*/
275
public void returnLease(Lease lease) throws Exception;
276
277
/**
278
* Return multiple leases
279
*/
280
public void returnAll(Collection<Lease> leases) throws Exception;
281
}
282
283
/**
284
* Represents a lease from a semaphore
285
*/
286
public class Lease implements Closeable {
287
/**
288
* Get the data associated with this lease
289
*/
290
public byte[] getData();
291
292
/**
293
* Get the node name for this lease
294
*/
295
public String getNodeName();
296
297
/**
298
* Close/return this lease
299
*/
300
public void close() throws IOException;
301
}
302
```
303
304
**Usage Example:**
305
306
```java
307
InterProcessSemaphoreV2 semaphore = new InterProcessSemaphoreV2(client, "/app/semaphore", 3);
308
309
Lease lease = semaphore.acquire(5, TimeUnit.SECONDS);
310
if (lease != null) {
311
try {
312
// Only 3 processes can be here simultaneously
313
System.out.println("Acquired semaphore lease");
314
// ... do work
315
} finally {
316
semaphore.returnLease(lease);
317
}
318
} else {
319
System.out.println("Could not acquire semaphore lease");
320
}
321
```
322
323
### Locker Utility
324
325
Utility class for try-with-resources lock acquisition pattern.
326
327
```java { .api }
328
/**
329
* Utility for using locks with try-with-resources
330
*/
331
public class Locker implements Closeable {
332
/**
333
* Create a new Locker for the given lock
334
* @param lock the lock to manage
335
* @param time maximum time to wait for acquisition
336
* @param unit time unit
337
*/
338
public Locker(InterProcessLock lock, long time, TimeUnit unit) throws Exception;
339
340
/**
341
* Release the managed lock
342
*/
343
public void close() throws IOException;
344
}
345
```
346
347
**Usage Example:**
348
349
```java
350
InterProcessMutex lock = new InterProcessMutex(client, "/app/locks/resource");
351
352
try (Locker locker = new Locker(lock, 10, TimeUnit.SECONDS)) {
353
// Lock is automatically acquired here and released when leaving the try block
354
System.out.println("Lock acquired, doing work...");
355
// ... do work
356
} // Lock is automatically released here
357
```
358
359
### Revocable Interface
360
361
Interface for locks that can be revoked by external processes.
362
363
```java { .api }
364
/**
365
* Interface for locks that can be revoked
366
*/
367
public interface Revocable<T> {
368
/**
369
* Make the lock revocable with the given listener
370
* @param listener listener to be called when revocation is requested
371
*/
372
void makeRevocable(RevocationListener<T> listener);
373
}
374
375
/**
376
* Listener interface for lock revocation events
377
*/
378
public interface RevocationListener<T> {
379
/**
380
* Called when revocation is requested
381
* @param forLock the lock being revoked
382
*/
383
void revocationRequested(T forLock);
384
}
385
```