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

Paw*_*wel 0 java volatile android-studio

volatile当多个并发线程读/写变量时需要修饰符。

是否有工具可以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.");
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

测试算法的代码:

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;
}
Run Code Online (Sandbox Code Playgroud)

rzw*_*oot 6

不,不可能。

volatile当多个并发线程读/写变量时需要修饰符。

这是完全错误的。

任何由多个线程访问的字段(至少有一个正在写入)都需要“发生前”保护。

volatile只是获取它的一种方法。synchronized是另一个。还有更奇特的方式。

哪个代码执行此操作?这……无法说清楚。在编译时不可能知道哪一行代码可能在哪个线程下运行。线程模型的设置方式以及暂停问题本身,这在数学上是不可能做到的。

这仅留下一条路线:

拥有一个虚拟机,对整个系统中每个非易失性字段的每次写入进行簿记,标记当时哪些锁处于活动状态、粗略的时间戳和堆栈跟踪。

这是一个令人难以置信的记账量,即使是在拥有大量内存的强大手机上,这也会让速度变得缓慢。但是,让我们这样做吧,并要求开发人员或测试人员在使用手机上的每个功能时耐心等待。

系统运行很长一段时间后,会发现字段访问在时间上似乎是交错的,并且没有共享活动锁。吐出这些访问:瞧,有一个列表,开发人员需要检查正在发生的情况,并可能添加某种锁定机制。可能是“标记字段volatile”,但更有可能的是您应该做其他事情来确保正确控制并发访问;volatile有点松散,大多数并发原则都不能用volatile字段正确编写。

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

  • JVM 还必须记录每个变量的每次读取,以检查它是否针对先前的写入得到了正确的保护。并且记住变量访问时所有活动的锁是不够的,因为在获取和释放之间存在有效的访问方案。例如,并行流操作可以在不持有任何锁的情况下对非并发集合进行并发访问,并且仍然是正确的。同时,正如您所提到的,不正确的使用并不意味着您可以使用“易失性”来修复它。 (2认同)