Sleep with lock held¶
ID: java/sleep-with-lock-heldKind: problemSecurity severity: Severity: errorPrecision: mediumTags: - quality - reliability - correctness - concurrency - performance - external/cwe/cwe-833Query suites: - java-security-and-quality.qls
Click to see the query in the CodeQL repository
CallingThread.sleep with a lock held may lead to very poor performance or even deadlock. This is becauseThread.sleep does not cause a thread to release its locks.
Recommendation¶
Thread.sleep should be called only outside of asynchronized block. However, a better way for threads to yield execution time to other threads may be to use either of the following solutions:
The
java.util.concurrentlibraryThe
waitandnotifyAllmethods
Example¶
In the following example of the problem, two threads,StorageThread andOtherThread, are started. Both threads output a message to show that they have started but thenStorageThread lockscounter and goes to sleep. The lock preventsOtherThread from lockingcounter, so it has to wait untilStorageThread has woken up and unlockedcounter before it can continue.
classStorageThreadimplementsRunnable{publicstaticIntegercounter=0;privatestaticfinalObjectLOCK=newObject();publicvoidrun(){System.out.println("StorageThread started.");synchronized(LOCK){// "LOCK" is locked just before the thread goes to sleeptry{Thread.sleep(5000);}catch(InterruptedExceptione){...}}System.out.println("StorageThread exited.");}}classOtherThreadimplementsRunnable{publicvoidrun(){System.out.println("OtherThread started.");synchronized(StorageThread.LOCK){StorageThread.counter++;}System.out.println("OtherThread exited.");}}publicclassSleepWithLock{publicstaticvoidmain(String[]args){newThread(newStorageThread()).start();newThread(newOtherThread()).start();}}
To avoid this problem,StorageThread should callThread.sleep outside thesynchronized block instead, so thatcounter is unlocked.
References¶
Java API Specification:Thread.sleep(),Object.wait(),Object.notifyAll(),java.util.concurrent.
Common Weakness Enumeration:CWE-833.