What is the volatile keyword useful for?

前端 未结 23 2673
闹比i
闹比i 2020-11-21 05:32

At work today, I came across the volatile keyword in Java. Not being very familiar with it, I found this explanation.

Given the detail in which that arti

相关标签:
23条回答
  • 2020-11-21 05:58

    In my opinion, two important scenarios other than stopping thread in which volatile keyword is used are:

    1. Double-checked locking mechanism. Used often in Singleton design pattern. In this the singleton object needs to be declared volatile.
    2. Spurious Wakeups. Thread may sometimes wake up from wait call even if no notify call has been issued. This behavior is called spurious wakeup. This can be countered by using a conditional variable (boolean flag). Put the wait() call in a while loop as long as the flag is true. So if thread wakes up from wait call due to any reasons other than Notify/NotifyAll then it encounters flag is still true and hence calls wait again. Prior to calling notify set this flag to true. In this case the boolean flag is declared as volatile.
    0 讨论(0)
  • 2020-11-21 05:59

    volatile only guarantees that all threads, even themselves, are incrementing. For example: a counter sees the same face of the variable at the same time. It is not used instead of synchronized or atomic or other stuff, it completely makes the reads synchronized. Please do not compare it with other java keywords. As the example shows below volatile variable operations are also atomic they fail or succeed at once.

    package io.netty.example.telnet;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class Main {
    
        public static volatile  int a = 0;
        public static void main(String args[]) throws InterruptedException{
    
            List<Thread> list = new  ArrayList<Thread>();
            for(int i = 0 ; i<11 ;i++){
                list.add(new Pojo());
            }
    
            for (Thread thread : list) {
                thread.start();
            }
    
            Thread.sleep(20000);
            System.out.println(a);
        }
    }
    class Pojo extends Thread{
        int a = 10001;
        public void run() {
            while(a-->0){
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Main.a++;
                System.out.println("a = "+Main.a);
            }
        }
    }
    

    Even you put volatile or not results will always differ. But if you use AtomicInteger as below results will be always same. This is same with synchronized also.

        package io.netty.example.telnet;
    
        import java.util.ArrayList;
        import java.util.List;
        import java.util.concurrent.atomic.AtomicInteger;
    
        public class Main {
    
            public static volatile  AtomicInteger a = new AtomicInteger(0);
            public static void main(String args[]) throws InterruptedException{
    
                List<Thread> list = new  ArrayList<Thread>();
                for(int i = 0 ; i<11 ;i++){
                    list.add(new Pojo());
                }
    
                for (Thread thread : list) {
                    thread.start();
                }
    
                Thread.sleep(20000);
                System.out.println(a.get());
    
            }
        }
        class Pojo extends Thread{
            int a = 10001;
            public void run() {
                while(a-->0){
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Main.a.incrementAndGet();
                    System.out.println("a = "+Main.a);
                }
            }
        }
    
    0 讨论(0)
  • 2020-11-21 06:00

    The volatile key when used with a variable, will make sure that threads reading this variable will see the same value . Now if you have multiple threads reading and writing to a variable, making the variable volatile will not be enough and data will be corrupted . Image threads have read the same value but each one has done some chages (say incremented a counter) , when writing back to the memory, data integrity is violated . That is why it is necessary to make the varible synchronized (diffrent ways are possible)

    If the changes are done by 1 thread and the others need just to read this value, the volatile will be suitable.

    0 讨论(0)
  • 2020-11-21 06:00

    volatile variable is basically used for instant update (flush) in main shared cache line once it updated, so that changes reflected to all worker threads immediately.

    0 讨论(0)
  • 2020-11-21 06:01

    Volatile does following.

    1> Read and write of volatile variables by different threads are always from memory, not from thread's own cache or cpu register. So each thread always deals with the latest value. 2> When 2 different threads work with same instance or static variables in heap, one may see other's actions as out of order. See jeremy manson's blog on this. But volatile helps here.

    Following fully running code shows how a number of threads can execute in predefined order and print outputs without using synchronized keyword.

    thread 0 prints 0
    thread 1 prints 1
    thread 2 prints 2
    thread 3 prints 3
    thread 0 prints 0
    thread 1 prints 1
    thread 2 prints 2
    thread 3 prints 3
    thread 0 prints 0
    thread 1 prints 1
    thread 2 prints 2
    thread 3 prints 3
    

    To achieve this we may use the following full fledged running code.

    public class Solution {
        static volatile int counter = 0;
        static int print = 0;
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Thread[] ths = new Thread[4];
            for (int i = 0; i < ths.length; i++) {
                ths[i] = new Thread(new MyRunnable(i, ths.length));
                ths[i].start();
            }
        }
        static class MyRunnable implements Runnable {
            final int thID;
            final int total;
            public MyRunnable(int id, int total) {
                thID = id;
                this.total = total;
            }
            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (true) {
                    if (thID == counter) {
                        System.out.println("thread " + thID + " prints " + print);
                        print++;
                        if (print == total)
                            print = 0;
                        counter++;
                        if (counter == total)
                            counter = 0;
                    } else {
                        try {
                            Thread.sleep(30);
                        } catch (InterruptedException e) {
                            // log it
                        }
                    }
                }
            }
        }
    }
    

    The following github link has a readme, which gives proper explanation. https://github.com/sankar4git/volatile_thread_ordering

    0 讨论(0)
  • 2020-11-21 06:02

    Yes, I use it quite a lot - it can be very useful for multi-threaded code. The article you pointed to is a good one. Though there are two important things to bear in mind:

    1. You should only use volatile if you completely understand what it does and how it differs to synchronized. In many situations volatile appears, on the surface, to be a simpler more performant alternative to synchronized, when often a better understanding of volatile would make clear that synchronized is the only option that would work.
    2. volatile doesn't actually work in a lot of older JVMs, although synchronized does. I remember seeing a document that referenced the various levels of support in different JVMs but unfortunately I can't find it now. Definitely look into it if you're using Java pre 1.5 or if you don't have control over the JVMs that your program will be running on.
    0 讨论(0)
提交回复
热议问题