`
polygoncell
  • 浏览: 56120 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

如何正确实现多线程安全的singleton patterns

阅读更多

Singleton Pattern


Short Introduction

 

 

 

 

 

Singleton pattern, described in the GOF Design Patterns book, is one of the most easily understandable and on of the most frequently used pattern. The goal of the singleton pattern is to make sure that there is only one instance of this class in the system and allow other classes access this instance.

 

 

 

Case study

 

 

 

Today I tried to extend a exist MVC system in our project. Because only one instance of the Controller is needed in the system (typical Singleton pattern), a traditional singleton pattern was implemented here. The code is looked like:

 

 

 

public class Controller {

 

 

 

     private static Controller instance;

 

 

 

    private Controller()

 

 

 

    {

 

 

 

            // do something

 

 

 

    }

 



    public final static Controller getInstance(){ 

 

 



    public final static Controller getInstance(){ 

 

 

                      (A)

 

 

 

if (instance == null) {

 

 

 

                        (B)

 

 

 

            instance = new Controller();

 

 

 

        }

 

 

 

return instance;

 

 

 

    }

 

 

 

// some more methods

 

 

 

}   

 

 

 

The above shown code is, just like it described in almost all Design patterns books, is beautiful and correct based on the traditional implantation of singleton pattern.

 

 

 

Just at this time, our Team leader came to me, saw the implementation and told me at the first second that the traditional implementation is NOT thread safe! Yes! It is thread unsafe, after I read the code once again. Why? Let us make try: two threads T1 and T2 try to call the class Controller. When T1 goes to the position (B) in the above shown code, it sleeps. Then comes T2 to the position (A) and checks whether an instance of the Controller exists. Because T1 sleeps at the position (B) before an instance will be created, T2 can go into the block and create a new instance of Controller. Now T1 is awake, and what will it do? Just create another instance of Controller, because it is already in the block! So, great! TWO instance are created! It is no more singleton!

 

 

 

The first simple idea that I got in the first second, as you estimated, is adding the key word synchronized   before the method getInstance(). But this brings bad Performance.  As we knew, the normally used solution for such a problem is to moving the synchronizing into the method. That means to building a synchronized block in the method. The code should be looked like this:

 

 

 

public class Controller {

 

 

 

     private static Controller instance;

 

 

 

    private Controller()

 

 

 

    {

 

 

 

            // do something

 

 

 

    }

 

 

 

   

 

 

 

    public final static Controller getInstance(){ 

 

 

 

                        (A)

 

 

 

if (instance == null) {

 

 

 

                        (B)

 

 

 

            synchronized {

 

 

 

                        instance = new Controller();

 

 

 

            }

 

 

 

        }

 

 

 

return instance;

 

 

 

    }

 

 

 

 

 

 

 

// some more methods

 

 

 

}   

 

 

 

But This code is still thread unsafe! Why? Because it is only synchronized when an instance is created, the above described problem DOES still exist. T1 sleeps at (B), T2 goes through and create a new instance, T1 wakes up and create another one! If we move the synchronized block up to contain the whole if block, there is nothing difference with a synchronized method. So, synchronized is a bad idea.

 

 

 

We must find another way.

 

 

 

The Current most used  thread safe solution for this problem is to creating an instance of the class as class’s private property when the class is loaded. The instance can be accessed by calling the public getInstance() method. The correct code should be looked like:

 

 

 

  public class Controller {

 

 

 

     private static Controller instance = new Controller();

 

 

 

    private Controller()

 

 

 

    {

 

 

 

            // do something

 

 

 

    }

 

 

 

   

 

 

 

    public final static Controller getInstance(){ 

 

 

 

return instance;

 

 

 

    }

 

 

 

 

 

 

// some more methods

 

 

 

}   

 

 

 

One drawback of this solution is that an instance is created anyway, even if the instance will be never used.

 

 

 

分享到:
评论

相关推荐

    Design-Patterns:SingletonSingleton单线程安全,生成器,Observer(2),Factory方法,Strategy(2),Template方法,Decorator,Façade,Flyweight,Adapter

    2. **Singleton单线程安全**:这是对传统单例模式的改进,确保在多线程环境下也能正确地创建唯一实例,防止多个线程同时创建单例对象。 3. **生成器(Builder)**:将复杂对象的构建与表示分离,使得同样的构建过程...

    Design Patterns中英文版

    在多线程环境下,正确实现单例模式尤其重要,防止多个线程创建多个实例。 2. **工厂方法模式(Factory Method)**:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类...

    什么是单例,为什么我们必须使用

    3. **不易于进行并发控制**:虽然有线程安全的实现方式,但单例模式在多线程环境下仍需谨慎处理。 **总结**: 单例模式在软件设计中扮演着重要角色,特别是在需要全局共享和资源管理的场景。理解并正确使用单例可以...

    SingletonInSwift:Swift中的设计模式

    在这个版本的Singleton中,我们使用了一个信号量来确保初始化过程在多线程环境下是原子操作。当初始化完成时,信号量会释放,等待的线程可以继续执行。 除了上述实现,Swift 5.1引入了一种新的特性——`@static let...

    设计模式学习

    在多线程环境中,正确实现单例模式需要考虑线程安全问题。 2. 工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类。它将对象的创建延迟到子类,提供了更好的灵活性。 3. 建造者模式:将一个复杂...

    台湾人写的设计模式笔记

    4. **多执行线程模式(Multithreading Patterns)** 在Java中,多执行线程是并发编程的关键。这些模式包括线程池(Thread Pool)、守护线程(Daemon Thread)、锁(Locking Strategies)等。线程池可以有效地管理线程资源,...

    Batch Engine 源码

    6. **设计模式(Design Patterns)**: 为了实现可扩展性和模块化,开发者可能会在代码中应用各种设计模式,如观察者模式(Observer)用于事件监听,工厂模式(Factory)用于对象创建,单例模式(Singleton)用于保证...

    Pattens In Java.pdf

    - 当需要提高多线程环境下的性能时,因为不可变对象可以安全地在多个线程之间共享。 #### 1.4 标记接口(Marker Interface) **使用:** 标记接口是一种特殊的接口类型,它没有任何方法声明。它主要用于表示某种...

    软件体系结构---设计模式的java运行代码案例

    例如,单例模式可能有一个静态内部类实现,以保证线程安全并防止早期初始化;工厂模式可能会展示如何根据条件动态创建对象;而观察者模式则会展示如何定义发布/订阅关系,使得一个对象的状态改变可以通知其他对象。 ...

    设计模式学习笔记大全

    在多线程环境中,正确实现单例模式需要考虑线程安全,防止多个线程同时创建实例。通常使用双重检查锁定(Double-Checked Locking)或静态内部类等方式实现。 2. 工厂方法模式(Factory Method): Factory Method...

    设计模式.pdf_学习模式必备

    在多线程环境中,确保数据的一致性和程序的正确性非常重要,因此多线程模式对于处理并发问题尤为重要。 - **Guarded Suspension**:保护性暂停模式,允许线程等待条件满足后再继续执行。 - **Producer-Consumer**:...

    Android源码学习之单例模式应用及优点介绍

    《Head First Design Patterns》中提到的"double-checked locking"是一种优化过的懒汉式实现,它使用了volatile关键字来保证多线程环境下的正确性。代码如下: ```java public class Singleton { private ...

    PHP设计模式

    - 效率问题:某些设计模式,如单例模式在多线程环境下,如果没有做好线程安全处理,可能会引起性能问题。 因此,正确地理解和运用设计模式对于一个PHP程序员来说至关重要。在学习和使用设计模式的过程中,一定要...

    SourceCodeLibs_cpp:常用模块实现的源码库

    4. **并发与多线程(Concurrency and Multithreading)**: C++11及以后的版本提供了丰富的并发编程支持。库中可能包括线程(Thread)、互斥量(Mutex)、条件变量(Condition Variable)等同步原语的示例,以及如何进行...

    iOSBAT面试资料全集

    12. Multithreading:多线程编程是iOS开发中提升应用性能的重要技术,涉及线程的创建、同步、以及管理等。 13. Memory Management:内存管理是iOS开发中需要特别注意的部分,包括自动引用计数(ARC)的使用以及非...

    C++编程思想

    - 多线程(Thread)基础。 - 同步机制,如互斥锁(Mutexes)、条件变量(Condition Variables)等。 - 并发模式(Patterns)的最佳实践。 7. **设计模式**: - 常见的设计模式如单例模式(Singleton)、工厂模式(Factory)...

    学习JAVA-23种设计模式

    除了这23种模式,还有并发型模式和线程池模式,这些模式在多线程编程中尤其重要,用于管理和优化线程资源。 设计模式遵循六大原则: 1. 开闭原则:软件实体(类、模块、函数等)应对扩展开放,对修改关闭。 2. 里氏...

    FunctionAndAlgorithm:收集好的方法并实现基本的算法或设计模式

    4. **Java特性**:作为Java的一部分,此项目可能利用了Java的特性,如接口(Interfaces)、枚举(Enums)、泛型(Generics)、异常处理(Exceptions)、多线程(Multithreading)等。这些特性让Java成为一种强大的...

    StopwatchApp:CP3406 Prac03的秒表实用程序应用程序

    StopwatchApp是一款基于Java开发的秒表实用程序...综上所述,StopwatchApp的实现涵盖了Java编程的多个核心领域,包括多线程、时间处理、UI设计、事件驱动编程以及版本控制等,对于提升学生的综合编程技能有着重要作用。

Global site tag (gtag.js) - Google Analytics