According to the Java Language Specification [[JLS 05]], section 17.9 "Sleep and Yield":
It is important to note that neither
Thread.sleep
norThread.yield
have any synchronization semantics. In particular, the compiler does not have to flush writes cached in registers out to shared memory before a call toThread.sleep
orThread.yield
, nor does the compiler have to reload values cached in registers after a call toThread.sleep
orThread.yield
.
The assumption that thread suspension and yielding flush the cached registers and reload the values when execution resumes, is misleading and paves the way for potential coding errors.
Noncompliant Code Example
This noncompliant code example declares a nonvolatile Boolean
flag.
private Boolean done; while (!this.done) { Thread.sleep(1000); }
"The compiler is free to read the field this.done
just once, and reuse the cached value in each execution of the loop. This would mean that the loop would never terminate, even if another thread changed the value of this.done
." [[JLS 05]]. This occurs because Thread.sleep()
does not establish a [happens-before] relation.
Compliant Solution
This compliant solution declares the flag volatile
to ensure that updates to it are made visible across multiple threads.
private volatile Boolean done; while (!this.done) { Thread.sleep(1000); }
The volatile
flag establishes a happens-before relation between any thread that sets done
and this thread.
Risk Assessment
Relying on the synchronization semantics of Thread.yield()
and Thread.sleep()
methods can cause unexpected behavior.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
CON16- J |
low |
probable |
medium |
P4 |
L3 |
Automated Detection
TODO
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[[JLS 05]] section 17.9 "Sleep and Yield"
CON15-J. Ensure actively held locks are released on exceptional conditions 11. Concurrency (CON) CON17-J. Avoid using ThreadGroup APIs