Volatile

 Volatile:

  • When a field is declared as volatile, then the compiler and runtime are notified that the variable is shared.
  • The volatile variable always returns the most recent write by any thread.
  • Volatile variable performs no locking and will not block the thread, it makes lightweight synchronisation mechanism.
  • When thread A writes to a volatile variable and thread B reads the same variable, then the value written is immediately available to thread B while reading. Writing a volatile variable is like exiting a synchronized block and reading a volatile variable is like entering a synchronized block.
  • The volatile variable can only guarantee visibility. but locking can guarantee both visibility and atomicity.
    • Volatile=Visibility
    • Locking= Visibility & Atomicity

    Explanation:

Locks offer mutual exclusion and visibility

Mutual Exclusion: It means only one thread at a time can hold a given lock and can use the shared data.

Visibility: Its like ensuring that changes made to shared data prior to releasing a lock are made visible to another thread that acquires the lock.

with visibility, thread could see inconsistent values for shared variables.

  • Volatile is not recommended for increment operation i++ atomic.


When to use Volatile variables:


When all the below conditions are satisfied we can use a volatile variable.

1. When writing to the variable do not depend on its current value i.e increment operation i++. (or) when only single thread ever updates the value.

2. The variable does not involve invariants with other state variables i.e that relate multiple variables (such as "start <=end").

3. When locking is not required, while the variable is being accessed. 


When to use volatile variable and some pattern to follow:


Pattern 1: Status flag

In this case the volatile variable is a simple boolean status flag, i.e one-time life-cycle event will occur 


Example:

Here shutdown() is called from outside by another thread, here we just need visibility and the status flag doesn’t depend on any other state variable here its ideal to use volatile.


volatile boolean shutdownRequested;


...


public void shutdown() { 

shutdownRequested = true; 

}


public void doWork() { 

    while (!shutdownRequested) { 

        // do stuff

    }

}

In the above program, there is only one state transition its shutdownRequested goes from false to true and program shutdowns.

This pattern can be extended to the state change from back and forth true—> false, false—>true 


Pattern2:  one-time safe publication


public class BackgroundFloobleLoader {

    public volatile Flooble theFlooble;

 

    public void initInBackground() {

        // do lots of stuff

        theFlooble = new Flooble();  // this is the only write to theFlooble

    }

}

 

public class SomeOtherClass {

    public void doWork() {

        while (true) { 

            // do some stuff...

            // use the Flooble, but only if it is ready

            if (floobleLoader.theFlooble != null) 

                doSomething(floobleLoader.theFlooble);

        }

    }

}


Pattern #3: independent observations


public class UserManager {

    public volatile String lastUser;

 

    public boolean authenticate(String user, String password) {

        boolean valid = passwordIsValid(user, password);

        if (valid) {

            User u = new User();

            activeUsers.add(u);

            lastUser = user;

        }

        return valid;

    }

}


Pattern #4: the "volatile bean" pattern


@ThreadSafe

public class Person {

    private volatile String firstName;

    private volatile String lastName;

    private volatile int age;

 

    public String getFirstName() { return firstName; }

    public String getLastName() { return lastName; }

    public int getAge() { return age; }

 

    public void setFirstName(String firstName) { 

        this.firstName = firstName;

    }

 

    public void setLastName(String lastName) { 

        this.lastName = lastName;

    }

 

    public void setAge(int age) { 

        this.age = age;

    }

}


Pattern #5: The cheap read-write lock trick


@ThreadSafe

public class CheesyCounter {

    // Employs the cheap read-write lock trick

    // All mutative operations MUST be done with the 'this' lock held

    @GuardedBy("this") private volatile int value;

 

    public int getValue() { return value; }

 

    public synchronized int increment() {

        return value++;

    }

}



Reference:

https://www.ibm.com/developerworks/java/library/j-jtp06197/



Summary

Volatile variables are a simpler -- but weaker -- form of synchronization than locking, which in some cases offers better performance or scalability than intrinsic locking. If you follow the conditions for using volatile safely -- that the variable is truly independent of both other variables and its own prior values -- you can sometimes simplify code by using volatile instead of synchronized. However, code using volatile is often more fragile than code using locking. The patterns offered here cover the most common cases where volatile is a sensible alternative to synchronized. Following these patterns -- taking care not to push them beyond their limits -- should help you safely cover the majority of cases where volatile variables are a win.







Comments

Popular posts from this blog

Java 10 Features