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