...或者它是否包含竞争条件?
当程序的结果取决于其他不可控事件的顺序或时间时,就会出现竞争条件。当事件没有按照程序员预期的顺序发生时,它就会成为一个错误。 https://en.wikipedia.org/wiki/Race_condition
我们在 Eclipse 中搜索了竞态条件,以查看 Eclipse 及其插件中最常见的竞态条件类型。
在启动和调试 jJava 项目期间,Eclipse Luna 中的 vmlens 发现了以下类型的竞争条件:
完全没有同步
竞争条件的最常见原因是从不同的线程访问相同的字段而根本没有任何同步。
目的 |
数数 |
并发访问的字段 |
2065 |
跟踪的字段 |
27114 |
监视器 |
7162 |
锁具 |
427 |
线程 |
52 |
挥发性领域 |
2836 |
在此运行期间,2065 个不同的字段被多个线程访问,其中 4 个没有同步。
使用了 2836 个可变字段。对于另外 3 个字段,有必要将它们声明为易变的。这导致发现了第二种类型的竞争条件,即可见性问题。
能见度
一个字段被许多线程访问,但没有声明为易变的。
JVM 不会直接将字段更新写入主内存,而是首先写入寄存器或 CPU 的缓存。只要您的程序在 PC 的一个核心上运行,这就不是问题。但是如果线程在不同的内核上运行,它们可能看不到字段的更新。
此问题最常出现在布尔标志中。比如run方法中org.eclipse.equinox.internal.util.impl.tpt.timer.TimerImpl的terminated字段:
public void run() {
TimerQueueNode n = null;
while (!terminated) {
synchronized (sync) {
if (n == null && queue.isEmpty()) {
try {
sync.wait();
} catch (Exception e) {
}
// todo check if isEmpty is necessary
if (queue.isEmpty() || terminated) {
continue;
}
}
}
结论
对于 2065 个并发访问的字段, vmlens 发现了 7 个竞争条件。所有其他都由 7162 个监视器正确同步或声明为易失性。