字段自旋¶
ID: java/spin-on-field
Kind: problem
Security severity:
Severity: warning
Precision: medium
Tags:
- efficiency
- correctness
- concurrency
Query suites:
- java-security-and-quality.qls
在空循环语句的条件中反复读取非易失性字段可能会导致无限循环,因为编译器优化可能会将此字段访问移出循环。
示例¶
在以下示例中,方法 spin
在循环中反复测试字段 done
。该方法重复 while 循环,直到字段 done
的值由另一个线程设置。但是,编译器可以优化代码,如第二个代码片段所示,因为字段 done
没有标记为 volatile
,并且循环体中没有可以更改 done
值的语句。优化后的 spin
版本将永远循环,即使另一个线程将 done
设置为 true
也是如此。
class Spin {
public boolean done = false;
public void spin() {
while(!done){
}
}
}
class Spin { // optimized
public boolean done = false;
public void spin() {
boolean cond = done;
while(!cond){
}
}
}
建议¶
确保对该字段的访问已正确同步。或者,避免在字段上自旋,而是使用 wait
和 notifyAll
方法或 java.util.concurrent
库在线程之间进行通信。
参考¶
Java 语言规范:线程和锁。