Java:如何自动检查哪些字段需要挥发性修饰符?

发布于 2025-02-04 08:41:28 字数 1257 浏览 3 评论 0 原文

volatile 当多个并发线程读取/编写变量时,需要修改器。

是否有工具可以自动检测缺失挥发性修饰符,例如在Android Studio中?

算法:

for (Class c:allClasses) {
    for (Field f:allFields) {
        List<Method> allMethods = getCallHierarchy(field);
        
        for (Method m:allMethods) {
            List<Thread> threads = getCallingThreads();
            if (threads.size() > 1) {
                Log.w("Warning: field "+f+" is accessed by several threads.");
            }
        }
    }
}

测试算法的代码:

public class Foo {
    private int a; //accessed by only one Thread - ok
    private int b; //accessed by two Threads - show compiler warning

    public static void main(String[] args) {
        a = 10; //no race condition - ok
        
        b = 1;
        Thread th = new Thread(this::someMethod);
        th.start(); //update to field "b" might stay unnoticed for mainThread

        while(!isDone) {
            Thread.sleep(20); //wait for the other Thread to finish
        }

        b += 2;
        
        System.out.println(b); //3 or 6
    }
    
    private void someMethod() {
        b += 3;
        isDone = true;
    }

    private volatile boolean isDone = false;
}

volatile modifier is required when a variable is read/written by several concurrent Threads.

Are there tools that can detect missing volatile modifiers automatically, e.g. in Android Studio?

Algorithm:

for (Class c:allClasses) {
    for (Field f:allFields) {
        List<Method> allMethods = getCallHierarchy(field);
        
        for (Method m:allMethods) {
            List<Thread> threads = getCallingThreads();
            if (threads.size() > 1) {
                Log.w("Warning: field "+f+" is accessed by several threads.");
            }
        }
    }
}

Code for testing the algorithm:

public class Foo {
    private int a; //accessed by only one Thread - ok
    private int b; //accessed by two Threads - show compiler warning

    public static void main(String[] args) {
        a = 10; //no race condition - ok
        
        b = 1;
        Thread th = new Thread(this::someMethod);
        th.start(); //update to field "b" might stay unnoticed for mainThread

        while(!isDone) {
            Thread.sleep(20); //wait for the other Thread to finish
        }

        b += 2;
        
        System.out.println(b); //3 or 6
    }
    
    private void someMethod() {
        b += 3;
        isDone = true;
    }

    private volatile boolean isDone = false;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

独木成林 2025-02-11 08:41:28

不,不可能。

挥发性当通过几个并发线程读取/编写变量时,需要修改器。

这是不正确的。

多个线程访问的任何字段,至少也在写作,需要“发生”守卫。

volatile 只是 获得它的方法。 同步是另一个。还有更多异国情调的方式。

这是哪个代码?那是不可能说的。在编译时不可能知道哪种代码可能在哪个线程下运行。线程模型的设置方式,停止问题是它的本质,这在数学上是不可能的。

这会留下精确的一个路由:

具有一个虚拟机,用于 每个写入 每个系统中的每个非挥发性字段当时,锁定的锁定,粗糙的时间戳和堆栈。

那是一个令人难以置信的簿记量,即使在带有大量记忆的强烈手机上,这也会减慢爬网的速度。但是,让我们去做,并要求开发人员或测试人员在打电话上敲打所有功能时,辛苦地等待它。

在系统运行良好之后,查找字段访问该时间的访问似乎与时间相交并且没有共享的活动锁。吐出这些访问:瞧,有一个列表,开发人员需要检查发生了什么并可能添加某种锁定机制。可以是“标记字段 volatile ”,但是您应该做其他事情以确保并发访问得到正确控制; volatile 有点松散的大炮,大多数并发原则不能用 volatile 字段正确编写。

我不知道有任何这样的工具,但是至少现在您特别知道要寻找什么。

No, not possible.

volatile modifier is required when a variable is read/written by several concurrent Threads.

This is flat out incorrect.

Any field that is accessed by multiple threads, at least one which is also writing, needs 'Happens-Before' guarding.

volatile is just one way to get it. synchronized is another. There are even more exotic ways.

Which code does this? That's.. impossible to tell. It's not possible to know at compile-time which line of code is likely to run under which thread. The way the thread model is set up, the halting problem being what it is, this is mathematically impossible to do.

This leaves precisely one route:

Have a Virtual Machine that does bookkeeping for every write to every non-volatile field in the entire system, marking down which lock(s) were active at the time, a rough timestamp, and a stacktrace.

That is an unbelievable amount of bookkeeping, even on a beefy phone with a ton of memory this is going to slow things down to a crawl. But, let's do it, and ask the developer or tester to painstakingly wait it out whilst they hit every feature on the phone.

After the system's been running a good long while find field accesses that time-wise appear to interleave and which have no shared active locks. Spit these accesses out: Voila, there's a list where the developer will need to check out what's going on and likely add some sort of locking mechanism. Could be 'Mark the field volatile', but far more likely you should be doing something else to ensure concurrent access is properly controlled; volatile is a bit of a loose cannon, most concurrency principles cannot be properly written with volatile fields.

I'm not aware of any such tool, but at least now you know specifically what to look for.

煮酒 2025-02-11 08:41:28

您应该找到一个工具来检查是否需要挥发性修饰符的必要性,例如Intellij Idea具有插件:

Mike的想法扩展具有(Java + Kotlin)检查 Anomic可以用挥发性替换,

然后您可以使用分析在Intellij中运行Intellij命名检查|检查代码。

You should find a tool that gives an inspection for necessity of volatile modifier, for example IntelliJ IDEA has a plugin:

Mike's IDEA Extensions has a (Java + Kotlin) inspection Atomic can be replaced with volatile

Then you can run a named inspection in IntelliJ for the whole project using Analyze | Inspect Code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文