Using volatile for skipping method execution

Tags: ,



I’ve never used volatile very often. Is it possible to use it to skip method execution if another thread executing it? I think in the code below it’s still possible that multiple threads pass the check and execute the method. Isn’t it?

private static boolean volatile test = false;
...
    public void test() {
        if (test) {
            return;
        }
        test = true;
        try {
            System.out.println("test() started in Thread with ID " + Thread.currentThread().getId());
            Thread.sleep(10000);
            System.out.println("test() finished in Thread with ID " + Thread.currentThread().getId());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        test = false;
    }

Use case: The method can be run periodically but at the same time it can be triggered manually by a user. There is no reason to run it twice one after another by using synchronized keyword. Please, tell me it’s doable with volatile. Otherwise I don’t see any reason to understand it except for job interviews 🙂 Other solutions that aren’t based on volatile are welcome.

Answer

You can use a volatile AtomicBoolean, like this, to achieve your requirement.

// default false so that first-thread that test() can enter the logic block
// AtomicBoolean's value is inherently volatile, so no need to declare volatile here
private static final AtomicBoolean test = new AtomicBoolean(false);   


public void test() {
    if (test.compareAndSet(false, true)) {  // check if the test if previously false and if so update it to true
        try {
            System.out.println("test() started in Thread with ID " + Thread.currentThread().getId());
            Thread.sleep(10000);
            System.out.println("test() finished in Thread with ID " + Thread.currentThread().getId());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            test.set(false); // executing thread now re-sets the test value
        }
    }
}


Source: stackoverflow