javaandroidgreenrobot-eventbusgreenrobot-eventbus-3.0

Been looking at lot of third party library codes lately and see this code which is confusing me


So here is the piece of code from EventBus getDefault() static method which returns static instance of EventBus class.

/** Convenience singleton for apps using a process-wide EventBus instance. */
public static EventBus getDefault() {
    EventBus instance = defaultInstance;
    if (instance == null) {
        synchronized (EventBus.class) {
            instance = EventBus.defaultInstance;
            if (instance == null) {
                instance = EventBus.defaultInstance = new EventBus();
            }
        }
    }
    return instance;
}

I see that code first checks if instance is null and then in synchronized block again does the same check once more. Why is that.

What if I write it like this.

/** Convenience singleton for apps using a process-wide EventBus instance. */
public static EventBus getDefault() {
    EventBus instance = defaultInstance;
    if (instance == null) {
        synchronized (EventBus.class) {
            instance = EventBus.defaultInstance = new EventBus();
        }
    }
    return instance;
}

Is there something wrong with my version? What I am missing here?


Solution

  • In your code two threads can get inside of the if statement concurrently when instance is null. Then, one thread enters the synchronized block to initialize instance, while the other is blocked. When the first thread exits the synchronized block, the waiting thread enters and creates another Singleton object. Note that when the second thread enters the synchronized block, it does not check to see if instance is non-null.

    So we follow double check initialization, it includes:

    1. Check that the variable is initialized (without obtaining the lock). If it is initialized, return it immediately.
    2. Obtain the lock.
    3. Double-check whether the variable has already been initialized: if another thread acquired the lock first, it may have already done the initialization. If so, return the initialized variable.
    4. Otherwise, initialize and return the variable.

    Source