https://github.com/jsunsoftware/concurrent
Simplified Striped Lock
https://github.com/jsunsoftware/concurrent
java-8 lock striped thread
Last synced: 8 days ago
JSON representation
Simplified Striped Lock
- Host: GitHub
- URL: https://github.com/jsunsoftware/concurrent
- Owner: jsunsoftware
- License: apache-2.0
- Created: 2018-06-08T21:15:44.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2025-12-19T18:18:21.000Z (2 months ago)
- Last Synced: 2025-12-22T07:22:39.994Z (2 months ago)
- Topics: java-8, lock, striped, thread
- Language: Java
- Homepage:
- Size: 94.7 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# concurrent
Lightweight Java utility that simplifies working with striped locks based on Google Guava’s `Striped`. It provides a
small, expressive API (`ResourceLock`) to synchronize execution by a resource key (single or multiple), with optional
timeouts and interruptible variants.
Internally it uses Guava’s `Striped` to balance contention vs. parallelism. The legacy `StripedLock` interface still
exists but is deprecated since 2.0.2 in favor of the factory that returns `ResourceLock` instances.
Links:
- Guava
Striped: https://google.github.io/guava/releases/snapshot/api/docs/com/google/common/util/concurrent/Striped.html
- Javadoc (generated in project target): `target/reports/apidocs/index.html`
## Installation
Maven dependency:
```xml
com.jsunsoft.util
concurrent
2.1.0
```
## Quick start
Most users should create locks via `StripedLockFactory` and use the `ResourceLock` API.
```java
import com.jsunsoft.util.concurrent.locks.ResourceLock;
import com.jsunsoft.util.concurrent.locks.striped.StripedLockFactory;
import java.time.Duration;
public class Example {
public static void main(String[] args) {
ResourceLock lock = StripedLockFactory.of(8, Duration.ofSeconds(30)); // 8 stripes, 30s default timeout
String key = "taskA";
lock.lock(key, () -> {
// the code which must be executed under the lock for key "taskA"
});
}
}
```
If your critical section needs to return a value:
```java
import com.jsunsoft.util.concurrent.locks.ResourceLock;
import com.jsunsoft.util.concurrent.locks.striped.StripedLockFactory;
import java.time.Duration;
public class Example {
public static void main(String[] args) {
ResourceLock lock = StripedLockFactory.of(8, Duration.ofSeconds(30));
String key = "taskA";
String result = lock.lock(key, () -> {
// protected code
return "ok";
});
}
}
```
Note: You can throw your custom checked exception from the lambda and handle it outside of the `lock` method. The API is
generic for exceptions.
## Interruptible locking
If the current thread may be interrupted, use the `lockInterruptibly` methods. They throw `InterruptedException` if the
thread is interrupted while waiting.
```java
import com.jsunsoft.util.concurrent.locks.ResourceLock;
import com.jsunsoft.util.concurrent.locks.striped.StripedLockFactory;
import java.time.Duration;
public class Example {
public static void main(String[] args) throws InterruptedException {
ResourceLock lock = StripedLockFactory.of(8, Duration.ofSeconds(30));
lock.lockInterruptibly("taskA", () -> {
// code executed under lock, can be interrupted
});
}
}
```
Timeout-aware and interruptible variants are also available, for example:
```java
import com.jsunsoft.util.concurrent.locks.ResourceLock;
import com.jsunsoft.util.concurrent.locks.striped.StripedLockFactory;
import java.time.Duration;
public class Example {
public static void main(String[] args) throws InterruptedException {
ResourceLock lock = StripedLockFactory.of(8, Duration.ofSeconds(30));
lock.lockInterruptibly("taskA", Duration.ofSeconds(5), () -> {
// try to acquire within 5 seconds or throw LockAcquireException
});
}
}
```
## Lock with multiple keys
When you need to acquire multiple locks consistently (to avoid deadlocks) for a collection of keys:
```java
import com.google.common.collect.ImmutableList;
import com.jsunsoft.util.concurrent.locks.ResourceLock;
import com.jsunsoft.util.concurrent.locks.striped.StripedLockFactory;
import java.time.Duration;
public class Example {
public static void main(String[] args) {
ResourceLock lock = StripedLockFactory.of(8, Duration.ofSeconds(30));
lock.lock(ImmutableList.of("taskA", "taskB"), () -> {
// code executed while both keys are locked in a consistent order
});
}
}
```
All `lock*` methods also have overloads returning a value via a callback, and overloads that accept a
`Duration timeout`.
## Important semantics / gotchas
- **Striped semantics**: this library uses Guava `Striped`. It is *not* one-lock-per-key: different keys may map to the
same stripe.
This means “different keys run in parallel” is best-effort and depends on stripe count and key distribution.
- **Key stability requirement**: keys must have stable `hashCode()` / `equals()` while a lock is held. Avoid mutable
objects (and arrays) as keys.
- **Timeout for multiple keys is per-lock**: for collection-based methods, the timeout is applied to **each** individual
lock acquisition.
Worst-case wait time can be `N × timeout`.
## Choosing striped lock type
You can choose between eager and lazy-weak stripes via `StripedLockType`:
```java
import com.jsunsoft.util.concurrent.locks.ResourceLock;
import com.jsunsoft.util.concurrent.locks.striped.StripedLockFactory;
import com.jsunsoft.util.concurrent.locks.striped.StripedLockType;
import java.time.Duration;
public class Example {
public static void main(String[] args) {
ResourceLock lock = StripedLockFactory.of(StripedLockType.LAZY_WEAK_LOCK, 8, Duration.ofSeconds(30));
}
}
```
See Javadoc for the difference between `LOCK` and `LAZY_WEAK_LOCK` (mirrors Guava’s `Striped.lock` vs
`Striped.lazyWeakLock`).
## API overview
`ResourceLock` exposes the following groups of methods (simplified):
- `lock(resource, executable)` and `lock(resource, timeout, executable)`
- `lock(resourcesCollection, executable)` and timeout variants
- `lockInterruptibly(...)` counterparts for both single and multiple resources
- All above variants have callback overloads that return a value
- Convenience `lock(...)`/`unlock(...)` methods when you need manual control
If the lock cannot be obtained within the specified timeout, `LockAcquireException` is thrown. For interruptible
variants, `InterruptedException` can be thrown.
## Legacy note
The older `StripedLock` interface is deprecated since 2.0.2 and will be removed in 3.0.0. Prefer `StripedLockFactory`
which returns a `ResourceLock`.
If you still need it for migration purposes:
```java
import com.jsunsoft.util.concurrent.locks.StripedLock; // Deprecated
import com.jsunsoft.util.concurrent.locks.ResourceLock;
import com.jsunsoft.util.concurrent.locks.striped.StripedLockFactory;
import java.time.Duration;
public class Example {
public static void main(String[] args) {
ResourceLock legacy = StripedLockFactory.of(8, Duration.ofSeconds(30));
legacy.lock("key", () -> { /* ... */ });
}
}
```
## Building locally
This is a standard Maven project. To run tests and build:
```bash
mvn -q -DskipTests=false clean verify
```
## License
Apache License 2.0. See `LICENSE` file.