singleton with volatile in java

前端 未结 9 1004
暖寄归人
暖寄归人 2020-12-31 06:23
class MyClass
{
      private static volatile Resource resource;

      public static Resource getInstance()
      {
            if(resource == null)
                        


        
相关标签:
9条回答
  • 2020-12-31 06:27

    You are correct, multiple threads could try to create a Resource object. Volatile just guarantees that if one thread updates the reference, all other threads will see the new reference, not some cached reference. This is slower, but safer.

    If you require only a single resource that is lazy loaded, you need to do something like this:

    class MyClass
    {
          private static volatile Resource resource;
          private static final Object LOCK = new Object();
    
          public static Resource getInstance()
          {
                if(resource == null) { 
                    synchronized(LOCK) { // Add a synch block
                        if(resource == null) { // verify some other synch block didn't
                                               // write a resource yet...
                            resource = new Resource();
                        }
                    }
                }
                return resource;
          }
     }
    
    0 讨论(0)
  • 2020-12-31 06:29

    When applied to a field, the Java volatile guarantees that:

    1. (In all versions of Java) There is a global ordering on the reads and writes to a volatile variable. This implies that every thread accessing a volatile field will read its current value before continuing, instead of (potentially) using a cached value. (However, there is no guarantee about the relative ordering of volatile reads and writes with regular reads and writes, meaning that it's generally not a useful threading construct.)

    2. (In Java 5 or later) Volatile reads and writes establish a happens-before relationship, much like acquiring and releasing a mutex.

    More info.

    0 讨论(0)
  • 2020-12-31 06:32

    volatile keyword guarantees that read and write to that variable are atomic.

    According to the tutorial

    Reads and writes are atomic for all variables declared volatile
    

    Using volatile variables reduces the risk of memory consistency errors, because any write to a volatile variable establishes a happens-before relationship with subsequent reads of that same variable. This means that changes to a volatile variable are always visible to other threads. What's more, it also means that when a thread reads a volatile variable, it sees not just the latest change to the volatile, but also the side effects of the code that led up the change.

    0 讨论(0)
  • 2020-12-31 06:34

    You are correct, in this case the Resource may be constructed twice due to the race you describe. If you want to implement a singleton (without explicit locking) in Java 5+, use an enum singleton as described in answers to What is an efficient way to implement a singleton pattern in Java?.

    0 讨论(0)
  • 2020-12-31 06:43

    first of all, having a Singleton this way, you are essentially creating a global object which is a bad practice. I reckon you use Enums instead.

    0 讨论(0)
  • 2020-12-31 06:43

    Here is my suggestion to add volatile & synchronized together.

    Note: we still have to do double check.

    public class MySingleton {
        private static volatile MySingleton instance;
        private MySingleton() {}
    
        synchronized private static void newInstance() {
            if(instance == null) {
                instance = new MySingleton();
            }
        }
    
        public static MySingleton get() {
            if(instance == null) {
                newInstance();
            }
            return instance;
        }
    }
    
    0 讨论(0)
提交回复
热议问题