使用 volatile 跳过方法执行

Using volatile for skipping method execution

我从来没有经常使用 volatile。如果另一个线程正在执行它,是否可以使用它来跳过方法执行? 我认为在下面的代码中仍然有可能多个线程通过检查并执行该方法。不是吗?

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

用例: 该方法可以是运行周期性的,但同时也可以由用户手动触发。没有理由使用 synchronized 关键字一个接一个地 运行 两次。 请告诉我这对 volatile 是可行的。否则,除了工作面试,我看不出有任何理由去理解它:) 欢迎其他不基于 volatile 的解决方案。

您可以像这样使用 volatile AtomicBoolean 来实现您的要求。

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