Lockshard8+ years
A service stops answering at 02:14, right after its rates provider returned a 503. CPU is idle, no errors are logged, and the thread dump shows no deadlock. Every request thread is `WAITING (parking)` on the same `ReentrantLock$NonfairSync`, and the scheduler thread that last called `refresh()` is alive and sleeping. What happened, how do you find the owner, and what are the two fixes?
refresh() called lock.lock(), then client.fetchAll() threw on the 503, and the unlock() after it was never reached. The method exited by exception with the lock still held. A lock has no timeout of its own and nothing in the JVM notices a holder that has moved on, so the AQS state stays 1 with a thread as owner that will never call unlock. Each request thread that reads through lock.lock() enqueues and parks, and within a minute all of them are parked behind a lock whose owner is not waiting for anything. There is no cycle, so there is no deadlock to report; the service is hung by a leak. Fix one is the try/finally; fix two is that a read should not take the write lock at all.
PreviousHow do you cancel a thread, and what must you do when you catch InterruptedException?Next A rates cache is `rates.computeIfAbsent(ccy, c -> rateClient.fetch(c))` on a `ConcurrentHashMap`. When the provider's 30 ms call becomes a 12-second call, requests for currencies that were already cached start timing out, but only for some currencies. Explain exactly which calls block and which do not, and fix it without adding a library.