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;
    }
    

    总结

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

  • 相关阅读:
    python 基础——generate生成器
    python 基础——*args和**kwargs
    猴子补丁
    python 元类——metaclass
    javascript 数据类型
    C/C++语言实现单链表(带头结点)
    C++仿函数和回调函数的异同
    C++利用动态数组实现顺序表(不限数据类型)
    const的用法
    数据结构之线性表
  • 原文地址:https://www.cnblogs.com/YungMing/p/4346730.html
Copyright © 2011-2022 走看看