持有锁时休眠¶
ID: java/sleep-with-lock-held
Kind: problem
Security severity:
Severity: error
Precision: medium
Tags:
- reliability
- correctness
- concurrency
- external/cwe/cwe-833
Query suites:
- java-security-and-quality.qls
调用 Thread.sleep
时持有锁可能会导致性能极差甚至死锁。这是因为 Thread.sleep
不会导致线程释放其锁。
建议¶
应仅在 synchronized
块之外调用 Thread.sleep
。但是,线程让出执行时间给其他线程的更好方法可能是使用以下两种解决方案中的任何一种:
java.util.concurrent
库wait
和notifyAll
方法
示例¶
在以下问题示例中,启动了两个线程 StorageThread
和 OtherThread
。这两个线程都输出一条消息以显示它们已启动,但随后 StorageThread
锁定 counter
并进入休眠状态。该锁阻止 OtherThread
锁定 counter
,因此它必须等到 StorageThread
唤醒并解锁 counter
才能继续。
class StorageThread implements Runnable{
public static Integer counter = 0;
private static final Object LOCK = new Object();
public void run() {
System.out.println("StorageThread started.");
synchronized(LOCK) { // "LOCK" is locked just before the thread goes to sleep
try {
Thread.sleep(5000);
} catch (InterruptedException e) { ... }
}
System.out.println("StorageThread exited.");
}
}
class OtherThread implements Runnable{
public void run() {
System.out.println("OtherThread started.");
synchronized(StorageThread.LOCK) {
StorageThread.counter++;
}
System.out.println("OtherThread exited.");
}
}
public class SleepWithLock {
public static void main(String[] args) {
new Thread(new StorageThread()).start();
new Thread(new OtherThread()).start();
}
}
为了避免这个问题,StorageThread
应该在 synchronized
块之外调用 Thread.sleep
,以便释放 counter
锁。
参考文献¶
Java API 规范:Thread.sleep(),Object.wait(),Object.notifyAll(),java.util.concurrent。
常见漏洞枚举:CWE-833。