在退出两次之前,单个线程如何两次进入同步块?

时间:2014-10-20 01:42:01

标签: java android concurrency synchronization

单个线程如何在退出两次之前两次进入同步块?

在我的应用程序中,我实现了单例模式,并且我注意到日志显示单个线程正在进入同步块两次,然后退出两次。因此,有两个实例是不幸的。这怎么可能? (我对Java特别感兴趣)

public class Singleton {
    private static volatile Singleton mSingleton;
    private static final Object mInstanceLock = new Object();
    private Singleton() {
        // Basic initialization.
    }
    public static Singleton getInstance() {
        if (mSingleton == null) {
            log("before synchronized");
            synchronized (mInstanceLock) {
                log("in synchronized start");
                if (mSingleton == null) {
                    mSingleton = new Singleton();
                    log("in synchronized, new Singleton(), " + mSingleton.toString() +
                            " in thread " + Thread.currentThread().getName() +
                            "-" Thread.currentThread().getId());
                }
                log("in synchronized end");
            }
            log("after synchronized");
        }
        return mSingleton;
    }
}

输出,注意创建的不同对象,构造函数运行两次(我的程序中的每个日志实际输出当前的线程ID,但我在上面的代码中将其保留,以便它看起来有点整洁):< / p>

before synchronized, in thread id 1
in synchronized start, in thread id 1
before synchronized, in thread id 1
in synchronized start, in thread id 1
// Basic initialization.
in synchronized, new Singleton(), com.example.app.Singleton@42453090 in thread: main-1
in synchronized end, in thread id 1
after synchronized, in thread id 1
// Basic initialization.
in synchronized, new Singleton(), com.example.app.Singleton@424500b0 in thread: main-1
in synchronized end, in thread id 1
after synchronized, in thread id 1

关于我的问题,它似乎无法实现。所以,如果没有确切的答案,那么解释是什么导致日志显示同一个线程创建两个不同的&#34;单身&#34;也会很棒!

额外说明,以防万一:

  • 此代码在Android应用中运行。
  • 代码主要是单线程的,但不同的线程确实使用Singleton
  • 每次运行代码时都可以重复。
  • 所有&#34;同步之前的时间戳&#34;和&#34;在同步开始&#34;是相同的&#34;。
  • &#34;在同步结束时的时间戳&#34;和&#34;同步后#34;对离开约10毫秒。
  • 这不是愚人节的笑话大声笑。
  • 我不确定我能提供哪些其他信息,请告诉我......

评论中的更多信息:

  • log()只是输出到控制台。更具体地说,它在Android中调用android.util.Log.d(),这是控制台最基本的调试消息。
  • 这只是一个Java对象,没有其他继承。

0 个答案:

没有答案