quarkusio/quarkus · error · jakarta.enterprise.context.control.LockException
Read lock not acquired in ${time} ms
Error message
Read lock not acquired in ${time} ms What it means
Analogous to the write-lock case: @Lock(READ) with time > 0 uses tryLock(time, unit) on the read lock and throws LockException when the timeout expires. The shared resource is held in write mode (or by other readers preventing acquisition) longer than the allowed wait.
Source
Thrown at independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/LockInterceptor.java:93
if (readHoldCount > 0) {
// Re-aqcquire the read locks
for (int i = 0; i < readHoldCount; i++) {
rwl.readLock().lock();
}
}
rwl.writeLock().unlock();
}
}
}
private Object readLock(Lock lock, InvocationContext ctx) throws Exception {
boolean locked = false;
long time = lock.time();
try {
if (time > 0) {
locked = rwl.readLock().tryLock(time, lock.unit());
if (!locked) {
throw new LockException("Read lock not acquired in " + lock.unit().toMillis(time) + " ms");
}
} else {
rwl.readLock().lock();
locked = true;
}
return ctx.proceed();
} finally {
if (locked) {
rwl.readLock().unlock();
}
}
}
Lock getLock(ArcInvocationContext ctx) {
Lock lock = ctx.findIterceptorBinding(Lock.class);
if (lock == null) {
// This should never happen
throw new LockException("@Lock binding not found on business method " + ctx.getMethod());View on GitHub (pinned to e1c734241f)
Solutions
- Increase lock.time()/unit on the @Lock(READ) annotation.
- Reduce the duration/frequency of write-locked operations on the same bean.
- Consider splitting data so reads and writes lock less contended state.
- Set time = 0 to block indefinitely on the read lock if a hard timeout is not required.
Example fix
// before
@Lock(value = LockType.READ, time = 50, unit = TimeUnit.MILLISECONDS)
public Data get() { ... }
// after
@Lock(value = LockType.READ, time = 2, unit = TimeUnit.SECONDS)
public Data get() { ... } Defensive patterns
Strategy: retry
Validate before calling
if (unit.toMillis(time) < expectedReadDurationMs) {
throw new IllegalStateException("@Lock(READ) time " + time + " likely too small");
} Try / catch
try {
return bean.readOperation();
} catch (LockException e) {
// writer starvation: brief backoff then retry
Thread.sleep(50);
return bean.readOperation();
} Prevention
- Ensure writers hold the lock briefly so readers aren't starved
- Choose read timeouts larger than the slowest writer section
- Set time=0 to wait indefinitely if a hard bound is not needed
- Use fair locking or data partitioning if contention is chronic
When it happens
Trigger: Method annotated @Lock(value = READ, time = N, unit = X) invoked while a writer holds the lock (or is starving readers) for longer than N units.
Common situations: Readers competing with frequent/long writers; time bound set too small; platform writer preference (ReentrantReadWriteLock is non-fair by default) delaying readers.
Related errors
- Write lock not acquired in ${time} ms
- Unsupported @Lock type found on business method ${method}
- @Lock binding not found on business method ${method}
- Tests already in progress
- The application is stopping
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/ae527c8326f36485.
Report an issue: GitHub.