Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to ensure a block of code is executed only once in a multithreaded environment?

I have a non singleton actor that is creating an object that I want created only only once. How is this achieved? Can an actor be singleton? If yes, how?

class NonSingletonActor extends UntypedActor {

   public static onReceive(Object arg)  throws Exception {

         *block of code that needs to be executed once!*
} }
like image 461
user_mda Avatar asked Sep 24 '15 17:09

user_mda


1 Answers

An AtomicBoolean is great for this, and in particular its compareAndSet method. That method takes two arguments: an "expected" value and a new value. It atomically does three things: (a) checks whether the current value is equal to the expected value, (b) if so, updates the current value to the new value, and (c) returns true iff that update happened (that is, if the expected and old values were the same).

private static final AtomicBoolean hasRun = new AtomicBoolean(false);

...
if (hasRun.compareAndSet(false, true)) {
    // your code here
}

This code will check to see if hasRun has a "false" value (which is its initial state). If so, it'll set itself to "true" and run if's block; otherwise, it'll keep its current state and not run the if's block. Crucially, the check-and-set is atomic (as the class name implies), meaning that no two threads can simultaneously see a false value; one of them will see the false value and set it to true, without the other thread being able to "sneak in" between those two actions.

like image 153
yshavit Avatar answered Oct 12 '22 01:10

yshavit