并发调用单例类方法 [英] concurrent calls of singleton class methods

查看:212
本文介绍了并发调用单例类方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个singleton类:

I have a singleton class:

public class Singleton {
    private static Singleton istance = null;

    private Singleton() {}

    public synchronized static Singleton getSingleton() {
        if (istance == null)
            istance = new Singleton();
        return istance;
    }

    public void work(){
            for(int i=0; i<10000; i++){
                Log.d("-----------", ""+i);
            }
    }
}

work()function:

And multiple Threads are calling the work() function:

public class Main {

public static void main(String[] args) {

    new Thread (new Runnable(){
        public void run(){
            Singleton s = Singleton.getSingleton();
            s.work();}
    }).start();

    System.out.println("main thread");

    new Thread(new Runnable() { 
         public void run() {
             Singleton s = Singleton.getSingleton();
                s.work();
         }
    }).start();
}
}



我注意到两个线程并发运行,两个工作函数同时被实例化。

I noticed the two Threads are running concurrently, as if two work functions were instantiated at the same time.

我想要最后一个线程代替上一个线程,而不是并发。是否可以在java中使第二个调用重写第一次调用的内存空间?

I want the last thread to be run in place of the previous thread, rather then concurrently. Is it possible in java to make the second call override the memory space of the first call?

推荐答案

> getSingleton()方法尝试延迟初始化SINGLETON实例,但它有以下问题:

Your getSingleton() method is attempting to lazily initializing the SINGLETON instance, but it has the following problems:

  • Access to the variable is not synchronized
  • The variable is not volatile
  • You are not using double checked locking

因此竞态条件AMY导致创建两个实例。

so a race condition AMY cause two instances to be created.

最好的和最简单的方法是安全地延迟初始化单例而不进行同步

The best and simplest was to safely lazily initialize a singleton without synchronization is as follows:

private static class Holder {
    static Singleton instance = new Singleton();
}

public static Singleton getSingleton() { // Note: "synchronized" not needed
    return Holder.instance;
}

这是线程安全的,因为java类加载器的契约是所有类在它们可以使用之前使它们的静态初始化完成。此外,类加载器不会加载类,直到它被引用。如果两个线程同时调用 getSingleton() Holder 类仍然只会加载一次,因此 new Singleton()只会被执行一次。

This is thread safe because the contract of the java class loader is that all classes have their static initialization complete before they may be used. Also, the class loader does not load a class until it is referenced. If two thread call getSingleton() simultaneously, the Holder class will still only get loaded once, and thus new Singleton() will only be executed once.

这还是懒惰的,因为 code>方法,因此 引用 getSingleton() >类只会在第一次调用 getSingleton()时加载。

This is still lazy because the Holder class is only referenced from getSingleton() method, so the Holder class will only be loaded when the first call to getSingleton() is made.

不需要同步,因为此代码依赖于类加载器的内部同步,这是防弹的。

Synchronization is not needed because this code relies on the class loader's internal synchronization, which is bullet proof.



此代码模式是使用单例模式的唯一方法。它是:


This code pattern is the only way to fly with singletons. It is:


  • 最快(不同步)

  • 最安全装载机安全)

  • 最干净(最少代码 - 双重检查锁定是丑陋的,并且它的功能很多)



其他类似的代码模式(同样安全,快捷)是用一个实例使用枚举但我认为这是笨拙的,意图不太清楚。


The other similar code pattern (equally safe and fast) is to use an enum with a single instance, but I find this to be clumsy and the intention is less clear.

这篇关于并发调用单例类方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆