zoukankan      html  css  js  c++  java
  • 创建单例

    背景

    很多时候,我们在网上,或者开源项目中,看到类似下面这样创建一个单例:

    +(MyClass *)singleton {
        static MyClass *shared = nil;
    
        if(shared == nil) {
            shared = [[MyClass alloc] init];
        }
        return shared;
    }
    

    但是,上面的代码在很多层面是错误的。首先,它不是线程安全的,当多个线程调用这个创建方法时,我们无法确保正确创建了一个实例,有时在苹果的官方例子中也是这么写的。

    如果你必须使用单例,可以使用dispatch_once()

    dispatch_once() 安全地解决了上面存在的问题:

    (1)它保证了在块中的代码将在应用中只调用一次

    (2)它是线程安全的

    (3)它比使用其他方法创建单例更快,比如使用@synchronize()

    @implementation Singleton
    static Singleton *shareSingleton = nil;
    
    +(Singleton*) shareInstance {
        @synchronized(self){  //加锁
            if (shareSingleton == nil) {
                shareSingleton = [[Singleton alloc] init];  
            }
        }
        return shareSingleton;
    }
    

    最佳实践

    所以,创建单例的最佳实践应该是:

    +(MyClass *)singleton {
        static dispatch_once_t pred;
        static MyClass *shared = nil;
    
        dispatch_once(&pred, ^{
            shared = [[MyClass alloc] init];
        });
        return shared;
    }
    

    总结

    在实际项目中,我们应该尽量避免过多使用单例,虽然单例不是什么魔鬼,但是能不用就不用。如果你必须使用单例,也要使用正确的方法来创建它。

  • 相关阅读:
    HDU 4666 Hyperspace【最远曼哈顿距离+优先队列】
    Set集合容器
    堆排序实现
    手机网站调试神器之chrome控制台
    CC Sereja and Ballons (主席树)
    Multiset多重集合容器
    ZOJ 3626 Treasure Hunt I
    hdu 2072
    poj 3498 (最大流,枚举汇点)
    排序算法--冒泡排序
  • 原文地址:https://www.cnblogs.com/YungMing/p/4346730.html
Copyright © 2011-2022 走看看