skip to Main Content

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;
}

2

Answers


  1. 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.

    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search