您的 Java Eclipse 插件线程安全吗?

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

...或者它是否包含竞争条件?

当程序的结果取决于其他不可控事件的顺序或时间时,就会出现竞争条件。当事件没有按照程序员预期的顺序发生时,它就会成为一个错误。 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 个监视器正确同步或声明为易失性。