Sunday, July 5, 2015

Java Volatile Misc
volatile only has relevance to modifications of the variable itself, not the object it refers to. It makes no sense to have a final volatile field because final fields cannot be modified. Just declare the field final and it should be fine.
Years ago when I last time demonstrated the multi-thread capability Java was still 32-bit, or at least there was 32-bit Java available. On 32 bits you could concurrently increment long variables and because the lower and upper 32 bits were handled in different processor shift there was a chance that two threads garbled some way the non-volatile variable. Now with Java 9 this is not the case. Now Java is 64-bit and I had to demonstrate the need for a volatile on 64-bit before anyone comes up the stupid idea that it was only needed for 32-bit
public class VolatileDemonstration implements Runnable {
    private Object o = null;
    private static final Object NON_NULL = new Object();
    public void run() {
        while( o == null );
        System.out.println("o is not null");
    public static void main(String[] args)
                           throws InterruptedException {
        VolatileDemonstration me = new VolatileDemonstration();
        new Thread(me).start();
        me.o = NON_NULL;

This code will never finish, unless you convert the field o volatile. We also need the 1000ms sleep to allow the JIT to optimize the code of the method run() after which it never reads the variable o ever again. The JIT assumes intra-thread semantics and takes the liberty to optimize the code that way. (Java Language Specification 17.4.7)
final field can not be volatile. Of course: a final can not change, there is no point to re-read it from the main memory and waste CPU cycles for the synchronization of any change of it between the CPU caches. But that is not true.
Final variables can be changed once.
This is something that novice Java developers tend to forget. When an object is created any final field has the zero value. In case of an object this value is null. The field has to get its final value until the end of the initialization process, that is until the end of the execution of the constructor (any constructor).
  • Final fields can be changed once. It is not true that they are not changing never (sic).
  • A thread may read the value of a final field once and it may not read it ever again. If the JVM runs for years the thread may keep the value in the thread context in some registry or CPU cache for years as long as it likes.
  • Never let this escape from the constructor.
  • Among other more trivial things the “never let this escape from the constructor” also means not to pass it as argument to a method that can be overridden or not under the control of the programmer, who is responsible for the current class.
  • Write well behaving code or else you will suffer the slings and arrows of your outrageous program.
To answer your question: Yes, I use a volatile variable to control whether some code continues a loop. The loop tests the volatile value and continues if it is true. The condition can be set to false by calling a "stop" method. The loop sees false and terminates when it tests the value after the stop method completes execution.

volatile is Not Always Enough

Even if the volatile keyword guarantees that all reads of a volatile variable are read directly from main memory, and all writes to a volatile variable are written directly to main memory, there are still situations where it is not enough to declare a variable volatile.
In the situation explained earlier where only Thread 1 writes to the shared counter variable, declaring the counter variable volatile is enough to make sure that Thread 2 always sees the latest written value.
In fact, multiple threads could even be writing to a shared volatile variable, and still have the correct value stored in main memory, if the new value written to the variable does not depend on its previous value. In other words, if a thread writing a value to the shared volatile variable does not first need to read its value to figure out its next value.
As soon as a thread needs to first read the value of a volatile variable, and based on that value generate a new value for the shared volatile variable, a volatile variable is no longer enough to guarantee correct visibility. The short time gap in between the reading of the volatile variable and the writing of its new value, creates an race condition where multiple threads might read the same value of the volatile variable, generate a new value for the variable, and when writing the value back to main memory - overwrite each other's values.

This safe publication guarantee applies only to primitive fields and object references. Programmers commonly use imprecise terminology and speak about "member objects." For the purposes of this visibility guarantee, the actual member is the object reference; the objects referred to (aka referents) by volatile object references are beyond the scope of the safe publication guarantee. Consequently, declaring an object reference to be volatile is insufficient to guarantee that changes to the members of the referent are published to other threads. A thread may fail to observe a recent write from another thread to a member field of such an object referent.
Furthermore, when the referent is mutable and lacks thread safety, other threads might see a partially constructed object or an object in a (temporarily) inconsistent state [Goetz 2007]. However, when the referent is immutable, declaring the reference volatile suffices to guarantee safe publication of the members of the referent. Programmers cannot use the volatile keyword to guarantee safe publication of mutable objects. Use of the volatile keyword can only guarantee safe publication of primitive fields, object references, or fields of immutable object referents.
final class Foo {
  private volatile int[] arr = new int[20];
  public int getFirst() {
    return arr[0];
  public void setFirst(int n) {
    arr[0] = n;
  // ...
Values assigned to an array element by one thread—for example, by calling setFirst()—might not be visible to another thread calling getFirst() because the volatile keyword guarantees safe publication only for the array reference; it makes no guarantee regarding the actual data contained within the array.
This problem arises when the thread that calls setFirst() and the thread that calls getFirst() lack a happens-before  relationship. A happens-before relationship exists between a thread that writes to a volatile variable and a thread that subsequently reads it. However, setFirst() and getFirst() read only from a volatile variable—the volatile reference to the array. Neither method writes to the volatile variable.
To ensure that the writes to array elements are atomic and that the resulting values are visible to other threads, this compliant solution uses the AtomicIntegerArray class defined in java.util.concurrent.atomic.
final class Foo {
  private final AtomicIntegerArray atomicArray =
    new AtomicIntegerArray(20);
  public int getFirst() {
    return atomicArray.get(0);
  public void setFirst(int n) {
  // ...
AtomicIntegerArray guarantees a happens-before relationship between a thread that calls atomicArray.set() and a thread that subsequently calls atomicArray.get().
declaring an array volatile does not give volatile access to its fields!. At least, it doesn't when elements of the array are accessed with "normal" Java syntax. In other words:
  • it is unsafe to call arr[x] = y on an array (even if declared volatile) in one thread and then expect arr[x] to return y from another thread;
  • on the other hand, it is safe to call arr = new int[] (or whatever) and expect another thread to then read the new array as that referenced by arr: this is what is meant by declaring the array reference volatile.
The AtomicIntegerArray class implements an int array whose individual fields can be accessed with volatile semantics, via the class's get() and set() methods. Calling arr.set(x, y) from one thread will then guarantee that another thread calling arr.get(x) will read the value y (until another value is read to position x).

Solution 2: re-write the array reference after each field write

This is slightly kludgy and slightly inefficient (since what would be one write now involves two writes) but I believe it is theoretically correct. After setting an element of the array, we re-set the array reference to be itself:
volatile int[] arr = new int[...];
arr[4] = 100;
arr = arr;
The marginal benefit of this technique could be:
  • it may allow you to fix some broken code with minimal changes if you have code already (incorrectly) using a volatile array and expecting thread-safe element access;
  • it saves us creating the wrapper object around the array (which is what happens with IntegerArray and LongArray);
  • it's more or less the only option for array types with no available atomic wrapper (e.g. a float array).
The volatile modifier also provides ordering guarantee because the compiler cannot re-order any code or operation which involves volatile variables (primitive and objects), but what is perhaps more important to know and remember is that volatile variable doesn't provide atomicity (except for write to the volatile double variable) and mutual exclusion, which is also the main difference between volatile and synchronizedkeyword.

There are certain restrictions with volatile keyword e.g. you cannot make a member variable both final and volatile at the same time, but you can make a static variable volatile in Java.

Any modification done on actual collection object e.g. adding or removing elements from ArrayList will not invoke happens-before guarantee or memory barrier refresh. 

The answer is, Yes, you can make an array (both primitive and reference type array e.g. an int array and String array) volatile in Java but only changes to reference pointing to an array will be visible to all threads, not the whole array
Volatile variables are not cached in registers or in caches where they are hidden from other processors, so a read of a volatile variable always returns the most recent write by any thread. ... The visibility effects of volatile variables extend beyond the value of the volatile variable itself. When thread A writes to a volatile variable and subsequently thread B reads that same variable, the values of all variables that were visible to A prior to writing to the variable become visible to B after reading the volatile variable.
— Java Concurrency in Practice - Brian Goetz, et al.
Use Volatile Fields When Writes Do Not Depend on Its Current Value
ublic class WorkerThread extends Thread {
    private volatile boolean isRunning = true;
    public void run() {
        while (isRunning) {
            // execute a task
    public void stopWorker() {
        isRunning = false;
Use Volatile Fields for Reading and Locks for Writing
java.util.concurrent.CopyOnWriteArrayList's get and set methods are an example of this tip:
public class CopyOnWriteArrayList < E >
    implements List < E > , RandomAccess, Cloneable, {
        private transient volatile Object[] array;
        final Object[] getArray() {
            return array;
        final void setArray(Object[] a) {
            array = a;
        private E get(Object[] a, int index) {
            return (E) a[index];
        public E get(int index) {
            return get(getArray(), index);
        public E set(int index, E element) {
            final ReentrantLock lock = this.lock;
            try {
                Object[] elements = getArray();
                E oldValue = get(elements, index);
                if (oldValue != element) {
                    int len = elements.length;
                    Object[] newElements = Arrays.copyOf(elements, len);
                    newElements[index] = element;
                } else {
                    // Not quite a no-op; ensures volatile write semantics
                return oldValue;
            } finally {
        // Other fields and methods omitted
The get method, line 13, simply reads the volatile field array and returns the value at the position index. Writing uses a lock to ensure that only one thread can modify the array at a given time. Line 18 acquires the lock and line 33 releases the lock. Writing requires copying the array when an element is changed, line 24, so that the reading threads do not see an inconsistent state. The writing thread then updates the array, line 25, and sets the new array to the volatile field array, line 26.
Using this tip only writes block writes. Compare this to using synchronized set and get methods, where each operation blocks all other operations. Or java.util.concurrent.locks.ReentrantReadWriteLock, where too many readers can lead to a starvation of writers.
“… the volatile modifier guarantees that any thread that reads a field will see the most recently written value.” - Josh Bloch
"The Java language also provides an alternative, weaker form of synchronization, volatile variables, to ensure that updates to a variable are propagated predictably to other threads.
When a field is declared volatile,the compiler and runtime are put on notice that this variable is shared and that operations on it should not be reordered with other memory operations. Volatile variables are not cached in registers or in caches where they are hidden from other processors, so a read of a volatile variable always returns the most recent write by any thread." - Java Concurrency In Practice(3.1.4 Volatile Variables)
class SharedObj
   // Changes made to sharedVar in one thread
   // may not immediately reflect in other thread
   static int sharedVar = 6;
Suppose that two threads are working on SharedObj. If two threads run on different processors each thread may have its own local copy of sharedVar. If one thread modifies its value the change might not reflect in the original one in the main memory instantly. This depends on the write policy of cache. Now the other thread is not aware of the modified value which leads to data inconsistency.
Below diagram shows that if two threads are run on different processors, then value of sharedVar may be different in different threads.
Note that write of normal variables without any synchronization actions, might not be visible to any reading thread (this behavior is called sequential consistency). Although most modern hardware provide good cache coherence therefore most probably the changes in one cache are reflected in other but it’s not a good practice to rely on hardware for to ‘fix’ a faulty application.
class SharedObj
   // volatile keyword here makes sure that
   // the changes made in one thread are 
   // immediately reflect in other thread
   static volatile int sharedVar = 6;
  1. Mutual Exclusion: It means that only one thread or process can execute a block of code (critical section) at a time.
  2. Visibility: It means that changes made by one thread to shared data are visible to other threads.
Java’s synchronized keyword guarantees both mutual exclusion and visibility. If we make the blocks of threads that modifies the value of shared variable synchronized only one thread can enter the block and changes made by it will be reflected in the main memory. All other thread trying to enter the block at the same time will be blocked and put to sleep.
In some cases we may only desire the visibility and not atomicity. Use of synchronized in such situation is an overkill and may cause scalability problems. Here volatile comes to the rescue. Volatile variables have the visibility features of synchronized but not the atomicity features. The values of volatile variable will never be cached and all writes and reads will be done to and from the main memory. However, use of volatile is limited to very restricted set of cases as most of the times atomicity is desired. For example a simple increment statement such as x = x + 1; or x++ seems to be a single operation but is s really a compound read-modify-write sequence of operations that must execute atomically.

For Java, “volatile” tells the compiler that the value of a variable must never be cached as its value may change outside of the scope of the program itself.
We typically use volatile keyword when we share variables with more than one thread in a multi-threaded environment, and we want to avoid any memory inconsistency errors due to the caching of these variables in the CPU cache.
Consider the following example of producer/consumer, where we are producing/consuming items one at a time .
public class ProducerConsumer {
  private String value = "";
  private boolean hasValue = false;
  public void produce(String value) {
    while (hasValue) {
      try {
      } catch (InterruptedException e) {
    System.out.println("Producing " + value + " as the next consumable");
    this.value = value;
    hasValue = true;
  public String consume() {
    while (!hasValue) {
      try {
      } catch (InterruptedException e) {
    String value = this.value;
    hasValue = false;
    System.out.println("Consumed " + value);
    return value;
We know that a computer consists of CPUs and Memory Units (and many other parts). Even though the main memory is where all of our program instructions and variables/data reside, during program execution CPUs can store copies of variables in their internal memory (which is known as CPU cache) for performance gain. Since modern computers now have more than one CPUs, there are more than one CPU caches as well.
In a multi-threaded environment, it’s possible for more than one threads to execute at the same time, each one in a different CPU, (although this is totally dependent on the underlying OS), and each one of them may copy variables from main memory into their corresponding CPU cache. When a thread accesses these variables, they will then then access these cached copies, not the actual ones in the main memory.
Now let’s assume that the two threads in our test are running on two different CPUs, and the hasValue flag has been cached on either one of them (or both). Now consider the following execution sequence –
  1. writerThread produces a value, and changes the hasValue to true. However, this update is only reflected in the cache, not in the main memory.
  2. readerThread is trying to consume a value, but it’s cached copy of the hasValue flag is set to false. So even though a value has been produced by the writerThread, it cannot consume it as the thread cannot break out of the sleeping loop (hasValue is false).
  3. Since the readerThread is not consuming the newly generated value, writerThread cannot proceed either as the flag is not being cleared, and hence it will be stuck in its sleeping loop.
  4. And we have a deadlock in our hands!
This situation will only change if the hasValue flag is synchronized across all caches, which totally depends on the underlying OS.
What’s the solution then? And how does volatile fit into this example?
If we just mark the hasValue flag as volatile, we can be sure that this type of deadlock will not occur –
private volatile boolean hasValue = false;
Marking a variable as volatile will force each thread to read the value of that variable directly from the main memory. Also each write to a volatile variable will be flushed into the main memory immediately. If the threads decide to cache the variable, it will be synced with the main memory on each read/write.

I See. Is This All Volatile Does, Forcing Threads to Read/Write Variables Directly From Memory?

Actually it has some further implications. Accessing a volatile variable establishes a happens-before relationship between program statements.

What is a Happens-before Relationship?

happens-before relationship between two program statements is sort a guarantee which ensures that any memory writes by one statement are visible to another statement.

How Does It Relate With Volatile?

When we write to a volatile variable, it creates a happens-before relationship with each subsequent read of that same variable. So any memory writes that have been done until that volatile variable write, will subsequently be visible to any statements that follow the read of that volatile variable.
// Definition: Some variables
private int first = 1;
private int second = 2;
private int third = 3;
private volatile boolean hasValue = false;
// First Snippet: A sequence of write operations being executed by Thread 1
first = 5;
second = 6;
third = 7;
hasValue = true;
// Second Snippet: A sequence of read operations being executed by Thread 2
System.out.println("Flag is set to : " + hasValue);
System.out.println("First: " + first);  // will print 5
System.out.println("Second: " + second); // will print 6
System.out.println("Third: " + third);  // will print 7

Let’s assume that the above two snippets being executed by two different threads – thread 1 and 2. When the first thread changes hasValue, it will not only flush this change to main memory, but it will also cause the previous three writes (and any other previous writes) to be flushed into the main memory as well! As a result, when the second thread accesses these three variables it will see all the writes made by thread 1, even if they were all cached before (and these cached copies will be updated as well)!
This is the exactly why we did not have to mark the value variable in our first example with volatile as well. Since we wrote to that variable before accessing hasValue, and read from it after reading hasValue, it was automatically synced with the main memory.
This has another interesting consequence. JVM is famous for its program optimization. Sometimes it reorders the program statements to boost performance without changing the output of the program. As an example, it can change the following sequence of statements –
first = 5;
second = 6;
third = 7;
Into this –
second = 6;
third = 7;
first = 5;
However, when the statements involve accessing a volatile variable, then it will never move a statement occurring before a volatile write after it. Which means, it will never transform this –

first = 5;  // write before volatile write
second = 6;  // write before volatile write
third = 7;   // write before volatile write
hasValue = true;
into this –

first = 5;
second = 6;
hasValue = true;
third = 7;  // Order changed to appear after volatile write! This will never happen!
Even though from the perspective of program correctness both of them seem to be equivalent. Note that the JVM is still allowed to reorder the first three writes among them as long as they all appear before the volatile write.
Similarly, the JVM will also not change the order of a statement which appears after a volatile variable read to appear before the access. Which means the following –

System.out.println("Flag is set to : " + hasValue);  // volatile read
System.out.println("First: " + first);  // Read after volatile read
System.out.println("Second: " + second); // Read after volatile read
System.out.println("Third: " + third);  // Read after volatile read
Will never be transformed by the JVM into this –

System.out.println("First: " + first);  // Read before volatile read! Will never happen!
System.out.println("Fiag is set to : " + hasValue); // volatile read
System.out.println("Second: " + second); 
System.out.println("Third: " + third);
However, the JVM can certainly reorder the last three reads among them, as long as they keep appearing after the volatile read.

I Sense a Performance Penalty Has to Be Paid For Volatile Variables.

You got that right, since volatile variables force main memory access, and accessing main memory is always way slower than accessing CPU caches. It also prevents certain program optimizations by JVM as well, further reducing the performance.

Can We Always Use Volatile Variables to Maintain Data Consistency Across Threads?

Unfortunately not. When more than one threads read and write to the same variable, then marking it as volatile is not enough to maintain consistency. Consider the following UnsafeCounter class –
public class UnsafeCounter {
  private volatile int counter;
  public void inc() {
  public void dec() {
  public int get() {
    return counter;
The code is pretty self-explanatory. We are incrementing the counter in one thread, and decrementing it in another by same number of times. After running this test we expect the counter to hold 0, but this is not guaranteed. Most of the times it will be 0, and some of the times it will be -1, -2, 1, 2 i.e., any integer value between the range [-5, 5].
Why does this happen? It happens because both the increment and the decrement operation of the counter are not atomic – they do not happen all at once. Both of them consists of multiple steps, and the sequence of steps overlap with each other. 
Yup. Using the synchronized keyword also establishes a happens-before relationship between statements. Entering a synchronized method/block establishes a happens-before relationship between the statements that appear before it and the ones inside the method/block. For a full list of what establishes a happens-before relationship, please go here.
What is volatile variable in Java - When to use | Java67
volatile variable in Java is a special variable which is used to signal threads, compiler that this particular variables values is going to be updated by multiple thread inside Java application. By making a variable volatile using volatile keyword in Java, application programmer ensures that its value should always been read from main memory and thread should not used cached value of that variable from there own stack.

From JDK5 on, volatile variable also guarantees "happens-before" relationship, which means not only other thread has visibility of latest value of volatile variable but also all the variable seen by the thread which has updated value of volatile variable before this threads sees it.

When to use Volatile variable in Java
1) Any variable which is shared between multiple threads should be made variable, in order to ensure that all thread must see latest value of volatile variable.

2) A signal to compiler and JIT to ensure that compiler does not change ordering or volatile variable and moves them out of synchronized context.

3) You want to save cost of synchronization as volatile variables are less expensive than synchronization.

Why not use volatile all the time?

Volatile read and write access is substantially slower.  When you write to a volatile field it stalls the entire CPU pipeline to ensure the data has been written to cache.  Without this, there is a risk the next read of the value sees an old value, even in the same thread (See AtomicLong.lazySet() which avoids stalling the pipeline)
The penalty can be in the order of 10x slower which you don’t want to be doing on every access.

What are the limitations of volatile?

A significant limitation is that operations on the field is not atomic, even when you might think it is.'s-volatile-boolean-AutomaticBoolean-analysis/
由以上测试用例可以看出,volatile boolean是无法保证线程安全的,在一个线程占用flag变量的时候,
A small toolkit of classes that support lock-free thread-safe programming on single variables. In essence, the classes in this package extend the notion of volatile values, fields, and array elements to those that also provide an atomic conditional update operation of the form:

boolean compareAndSet(expectedValue, updateValue);

This method (which varies in argument types across different classes) atomically sets a variable to the updateValue if it currently holds the expectedValue, reporting true on success. The classes in this package also contain methods to get and unconditionally set values, as well as a weaker conditional atomic update operation weakCompareAndSet described below.
 public static volatile AtomicBoolean flag = new AtomicBoolean(true);
 public static void main(String[] args) {
  for (int j = 0; j < 20; j++) {
   Thread t = new Thread(new Test());
 public void run() {
  if (flag.compareAndSet(true, false)) {

Atomic类不仅仅提供了对数据操作的线程安全保证,而且提供了一系列的语义清晰的方法,如incrementAndGet() 、getAndIncrement() 等,使用方便,Atomic的内部实现使用的是更加高效的CAS(compareand swap)+volatile,从而避免了synchronized的高开销,执行效率大幅提升,出于性能考虑强烈建议使用Atomic,而不是synchronized关键字。





在Java存储模型(Java Memory Model, JMM)中,重排序是十分重要的一节,特别是在并发编程中。JMM通过happens-before法则保证顺序执行语义,如果想要让执行操作B的线程观察到执行操作A的线程的结果,那么A和B就必须满足happens-before原则,否则,JVM可以对它们进行任意排序以提高程序性能。

volatile关键字可以保证变量的可见性,因为对volatile的操作都在Main Memory中,而Main Memory是被所有线程所共享的,这里的代价就是牺牲了性能,无法利用寄存器或Cache,因为它们都不是全局的,无法保证可见性,可能产生脏读。


          private int counter = 0;
          public int getCount ( ) {
                   int result = counter;
                   int newValue = counter + 1; // 1. 计算新值
                   counter = newValue;         // 2. 将新值赋值给原变量
                   return result;
          private int counter = 0;
          public synchronized int getCount ( ) {
                   return counter++;
          private int something = 0;
          public int getSomething ( ) {
                   return something;
          public void setSomething (int something) {
                   this.something = something;
    假设有多线程同时并发访问getSomething()和setSomething()方法,那么当一个线程通过调用setSomething()方法设置一个新的值时,其他调用getSomething()的方法是不是立即可以读到这个新值呢?这里的"this.something = something;" 是一个对int 类型的赋值,按照java 语言规范,对int的赋值是原子操作,这里不存在上面案例中的非原子操作的隐患。
    但是这里还是有一个重要问题,称为"内存可见性"。这里涉及到java内存模型的一系列知识,限于篇幅,不详尽讲述,不清楚这些知识点的可以自己翻翻资料,最简单的办法就是google一下这两个关键词"java 内存模型", "java 内存可见性"。或者,可以参考这个帖子"java线程安全总结",。
    解决这里的"内存可见性"问题的方式有两个,一个是继续使用 synchronized 关键字,代码如下
          private int something = 0;
          public synchronized  int getSomething ( ) {
                   return something;
          public synchronized  void setSomething (int something) {
                   this.something = something;
     另一个是使用volatile 关键字,
          private volatile int something = 0;
          public int getSomething ( ) {
                   return something;
          public void setSomething (int something) {
                   this.something = something;
    使用volatile 关键字的方案,在性能上要好很多,因为volatile是一个轻量级的同步,只能保证多线程的内存可见性,不能保证多线程的执行有序性。因此开销远比synchronized要小。
    让我们再回到开始的案例,因为我们采用直接在 getCount() 方法前加synchronized 的修改方式,因此不仅仅避免了非原子性操作带来的多线程的执行有序性问题,也"顺带"解决了内存可见性问题。
    OK,现在可以继续了,前面讲到可以通过在 getCount() 方法前加synchronized 的方式来解决问题,但是其实还有更方便的方式,可以使用jdk 5.0之后引入的concurrent包中提供的原子类,java.util.concurrent.atomic.Atomic***,如AtomicInteger,AtomicLong等。
        private AtomicInteger  counter = new AtomicInteger(0);
        public int getCount ( ) {
             return counter.incrementAndGet();
    Atomic类不仅仅提供了对数据操作的线程安全保证,而且提供了一系列的语义清晰的方法如incrementAndGet(),getAndIncrement,addAndGet(),getAndAdd(),使用方便。更重要的是,Atomic类不是一个简单的同步封装,其内部实现不是简单的使用synchronized,而是一个更为高效的方式CAS (compare and swap) + volatile,从而避免了synchronized的高开销,执行效率大为提升。限于篇幅,关于“CAS”原理就不在这里讲诉。
    1. ++操作不是原子操作
    2. 非原子操作有线程安全问题
    3. 并发下的内存可见性

    4. Atomic类通过CAS + volatile可以比synchronized做的更高效,推荐使用
Multithreading, Concurrency and Thread basics Questions
1) Can we make array volatile in Java?
Yes, you can make an array volatile in Java but only the reference which is pointing to an array, not the whole array. What I mean, if one thread changes the reference variable to points to another array, that will provide volatile guarantee, but if multiple threads are changing individual array elements they won't be having happens before guarantee provided by volatile modifier.

2) Can volatile make a non-atomic operation to atomic?
One example I have seen is having a long field in your class. If you know that a long field is accessed by more than one thread e.g. a counter, a price filed or anything, you better make it volatile. Why? because reading to a long variable is not atomic in Java and done in two steps, If one thread is writing or updating long value, it's possible for another thread to see half value (fist 32-bit). While reading/writing a volatile long or double (64 bit) is atomic.
3) What are practical uses of volatile modifier? 
One of the practical use of volatile variable is to make reading double and long atomic. Both double and long are 64-bit wide and they are read in two parts, first 32-bit first time and next 32-bit second time, which is non-atomic but volatile double and long read is atomic in Java. Another use of volatile variable is to provide a memory barrier, just like it is used inDisrupter framework. Basically, Java Memory model inserts a write barrier after you write to volatile variable and a read barrier before you read it. Which means, if you write to volatile field then its guaranteed that any thread accessing that variable will see the value you wrote and anything you did before doing that write into the thread is guaranteed to have happened and any updated data values will also be visible to all threads, because the memory barrier flushed all other writes to the cache.

4) What guarantee volatile variable provides? (answer)
volatile variables provide the guarantee about ordering and visibility e.g. volatile assignment cannot be re-ordered with other statements but in the absence of any synchronization instruction compiler, JVM or JIT are free to reorder statements for better performance. volatile also provides the happens-before guarantee which ensure changes made in one thread is visible to others. In some cases volatile also provide atomicity e.g. reading 64-bit data types like long and double are not atomic but read of volatile double or long is atomic.

Read full article from What is volatile variable in Java - When to use | Java67

No comments:

Post a Comment


Review (560) System Design (303) System Design - Review (195) Java (179) Coding (75) Interview-System Design (65) Interview (60) Book Notes (59) Coding - Review (59) to-do (45) Knowledge (39) Linux (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (29) Product Architecture (28) Big Data (27) Soft Skills (27) Concurrency (26) MultiThread (26) Miscs (25) Cracking Code Interview (24) Distributed (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) OOD Design (20) System Design - Practice (19) Security (17) Algorithm (15) How to Ace Interview (15) Brain Teaser (14) Redis (14) Google (13) Linux - Shell (13) Spark (13) Spring (13) Code Quality (12) How to (12) Interview-Database (12) Interview-Operating System (12) Tools (12) Architecture Principles (11) Company - LinkedIn (11) Testing (11) Resource (10) Search (10) Solr (10) Amazon (9) Cache (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Company - Uber (8) Interview - MultiThread (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Scalability (8) Cassandra (7) Company - Facebook (7) Design (7) Git (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Machine Learning (7) NoSQL (7) Trouble Shooting (7) C++ (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) API Design (4) Be Architect (4) Big Fata (4) C (4) Company Product Architecture (4) Data structures (4) Design Principles (4) Facebook (4) GeeksforGeeks (4) Generics (4) Google Interview (4) Hardware (4) JDK8 (4) Optimization (4) Product + Framework (4) Shopping System (4) Source Code (4) Web Service (4) node.js (4) Back-of-Envelope (3) Company - Pinterest (3) Company - Twiiter (3) Company - Twitter (3) Consistent Hash (3) Elasticsearch (3) GOF (3) Game Design (3) GeoHash (3) Growth (3) Guava (3) Interview-Big Data (3) Interview-Linux (3) Interview-Network (3) Java EE Patterns (3) Javarevisited (3) Map Reduce (3) Math - Probabilities (3) Performance (3) Puzzles (3) Python (3) RateLimiter (3) Resource-System Desgin (3) Scala (3) UML (3) ZooKeeper (3) geeksquiz (3) AI (2) AngularJS (2) Behavior Question (2) Bugs (2) Coding Interview (2) Company - Netflix (2) Crawler (2) Cross Data Center (2) Data Structure Design (2) Database-Shard (2) Debugging (2) Docker (2) Garbage Collection (2) Go (2) Hadoop (2) Html (2) Interview - Soft Skills (2) Interview-Miscs (2) Interview-Web (2) JDK (2) Logging (2) POI (2) Papers (2) Programming (2) Project Practice (2) Random (2) Software Desgin (2) System Design - Feed (2) Thread Synchronization (2) Video (2) reddit (2) Ads (1) Advanced data structures (1) Algorithm - Review (1) Android (1) Approximate Algorithms (1) Base X (1) Bash (1) Books (1) C# (1) CSS (1) Chrome (1) Client-Side (1) Cloud (1) CodingHorror (1) Company - Yelp (1) Counter (1) DSL (1) Dead Lock (1) Difficult Puzzles (1) Distributed ALgorithm (1) Eclipse (1) Facebook Interview (1) Function Design (1) Functional (1) GoLang (1) How to Solve Problems (1) ID Generation (1) IO (1) Important (1) Internals (1) Interview - Dropbox (1) Interview - Project Experience (1) Interview Stories (1) Interview Tips (1) Interview-Brain Teaser (1) Interview-How (1) Interview-Mics (1) Interview-Process (1) Java Review (1) Jeff Dean (1) Joda (1) LeetCode - Review (1) Library (1) LinkedIn (1) LintCode (1) Mac (1) Micro-Services (1) Mini System (1) MySQL (1) Nigix (1) NonBlock (1) Process (1) Productivity (1) Program Output (1) Programcreek (1) Quora (1) RPC (1) Raft (1) Reactive (1) Reading (1) Reading Code (1) Refactoring (1) Resource-Java (1) Resource-System Design (1) Resume (1) SQL (1) Sampling (1) Shuffle (1) Slide Window (1) Spotify (1) Stability (1) Storm (1) Summary (1) System Design - TODO (1) Tic Tac Toe (1) Time Management (1) Web Tools (1) algolist (1) corejavainterviewquestions (1) martin fowler (1) mitbbs (1)

Popular Posts