{"record":{"id":"ae527c8326f36485","repo":"quarkusio/quarkus","slug":"read-lock-not-acquired-in-time-ms","errorCode":null,"errorMessage":"Read lock not acquired in ${time} ms","messagePattern":"Read lock not acquired in (.+?) ms","errorType":"exception","errorClass":"jakarta.enterprise.context.control.LockException","httpStatus":null,"severity":"error","filePath":"independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/LockInterceptor.java","lineNumber":93,"sourceCode":"                if (readHoldCount > 0) {\n                    // Re-aqcquire the read locks\n                    for (int i = 0; i < readHoldCount; i++) {\n                        rwl.readLock().lock();\n                    }\n                }\n                rwl.writeLock().unlock();\n            }\n        }\n    }\n\n    private Object readLock(Lock lock, InvocationContext ctx) throws Exception {\n        boolean locked = false;\n        long time = lock.time();\n        try {\n            if (time > 0) {\n                locked = rwl.readLock().tryLock(time, lock.unit());\n                if (!locked) {\n                    throw new LockException(\"Read lock not acquired in \" + lock.unit().toMillis(time) + \" ms\");\n                }\n            } else {\n                rwl.readLock().lock();\n                locked = true;\n            }\n            return ctx.proceed();\n        } finally {\n            if (locked) {\n                rwl.readLock().unlock();\n            }\n        }\n    }\n\n    Lock getLock(ArcInvocationContext ctx) {\n        Lock lock = ctx.findIterceptorBinding(Lock.class);\n        if (lock == null) {\n            // This should never happen\n            throw new LockException(\"@Lock binding not found on business method \" + ctx.getMethod());","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/LockInterceptor.java#L75-L111","documentation":"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.","triggerScenarios":"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.","commonSituations":"Readers competing with frequent/long writers; time bound set too small; platform writer preference (ReentrantReadWriteLock is non-fair by default) delaying readers.","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."],"exampleFix":"// before\n@Lock(value = LockType.READ, time = 50, unit = TimeUnit.MILLISECONDS)\npublic Data get() { ... }\n// after\n@Lock(value = LockType.READ, time = 2, unit = TimeUnit.SECONDS)\npublic Data get() { ... }","handlingStrategy":"retry","validationCode":"if (unit.toMillis(time) < expectedReadDurationMs) {\n    throw new IllegalStateException(\"@Lock(READ) time \" + time + \" likely too small\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    return bean.readOperation();\n} catch (LockException e) {\n    // writer starvation: brief backoff then retry\n    Thread.sleep(50);\n    return bean.readOperation();\n}","preventionTips":["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"],"tags":["locking","concurrency","timeout","arc"],"backgroundTag":"lock-acquisition-timeout","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}