单例模式
    在建模的时候,如果这个东西确实只需要一个对象,多余的对象都是无意义的,那么就考虑用单例模式。比如定位管理(CLLocationManager),硬件设备就只有一  个,弄再多的逻辑对象意义不大。所以就会考虑用单例
        1) 系统为我们提供的单例类有哪些?
              UIApplication(应用程序实例类)
              NSNotificationCenter(消息中心类)
              NSFileManager(文件管理类)
              NSUserDefaults(应用程序设置)
              NSURLCache(请求缓存类)
              NSHTTPCookieStorage(应用程序cookies池)
        2) iOS单例的创建

a. 单例类需要保证只有一个实例,因此在第一次访问这个实例的时候才创建,之后访问直接取已经创建好的实例

+(instancetype)shareInstance {

              static Singleton *singleteon;

              if (!singleteon ) {

                   singleteon = [[Singleton alloc] init];

               }

               return singleteon;

         }

单线程单例存在一些弊端,在多线程的情况下,会产生线程不安全的情况。严格意义上来说,我们还需要把alloc方法变为私有方法才行,严格的单例是

不允许再创建其他实例的,而alloc方法可以在外部任意生成实例。但是考虑到alloc属于NSObject,iOS中无法将alloc变成私有方法,最多只能覆盖alloc

让其返回空。不过个人不建议这么做,一般情况下对alloc不做特殊处理。系统的单例也未对alloc做任何处理.

b. @synchronized单例

上面单线程单例,在多线程情况下,可能会出现一些问题。如果两个线程同时调用shareInstanc,可能会创建出2个singleton出来。所以在对多线程情况下,

我们需要使用@synchronize来加锁.

+(instancetype)shareInstance {

               static Singleton *singleton;

               @synchronized (self) {

                    if (!singleton) {

                           singleton = [[Singleton alloc] init];

                    }   

                }

                return singleton;

          }

加锁以后,当多个线程同时调用shareInstance时,由于@synchronized已经加锁,只能有一个线程创建singleton实例。这样就解决了多线程调用单例的问题。

c.dispatch_once单例

使用@synchronized虽然一定程度上解决了多线程的问题,但并不完美。因为只有在singleton未创建时,加锁才是必要的。如果singleton已经创建,这个时

候还加锁的话,会影响性能。
              
在iOS中,GCD为我们提供方便又高效的方法—dispatch_once

        +(instancetype)shareInstance{
static Singleton *singleton;
static dispatch_once_t onceToken; //1.onceToken = 0;
dispatch_once(&onceToken,^{
NSLog(@"%ld",onceToken); //2.onceToken = 140734537148864
singleton = [[Singleton alloc] init];
});
NSLog(@"%ld",onceToken); //3.onceToken = -1
return singleton;
}

               dispatch_once为什么能做到既解决同步多线程问题

               dispatch_once的原理:
               dispatch_once主要是根据onceToken的值来决定怎么去执行代码。
               1.当onceToken = 0时,线程执行dispatch_onceblock中代码
               2.当onceToken = -1时,线程跳过dispatch_onceblock中代码不执行
               3.当onceToken为其他值时,线程被阻塞,等待onceToken值改变
               当线程调用shareInstance,此时onceToken = 0,调用block中的代码,此时onceToken的值变为140734537148864。当其他线程再调用shareInstance

方法时,onceToken的值已经是140734537148864了,线程阻塞。当block线程执行完block之后,onceToken变为-1.其他线程不再阻塞,跳过block

下次再调用shareInstance时,block已经为-1.直接跳过block

 

ios 单例的再次理解的更多相关文章

  1. 【iOS 单例设计模式】底层解析与运用

    [iOS 单例设计模式]底层解析与运用 一.单例设计名词解释: (官方解释)单例模式确保一个类只有一个实例,自行提供这个实例并向整个系统提供这个实例.(形象比喻)程序 — 公司   单例实例 - 管理 ...

  2. iOS单例创建的一点疑惑

    线程安全的单例常用写法, +(AccountManager *)sharedManager{ static AccountManager *defaultManager = nil; disptch_ ...

  3. iOS单例设计模式具体解说(单例设计模式不断完好的过程)

    在iOS中有非常多的设计模式,有一本书<Elements of Reusable Object-Oriented Software>(中文名字为<设计模式>)讲述了23种软件设 ...

  4. iOS 单例传值遇见问题

    单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 1.单例模式的要点: 显然单例模式的要点有三个:一是某个类只能有一个实例: ...

  5. iOS单例的两种实现

    单例模式算是开发中比较常见的一种模式了.在iOS中,单例有两种实现方式(至少我目前只发现两种).根据线程安全的实现来区分,一种是使用@synchronized,另一种是使用GCD的dispatch_o ...

  6. iOS 单例用法

    单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 1.单例模式的要点: 显然单例模式的要点有三个:一是某个类只能有一个实例: ...

  7. iOS单例详解

    单例:整个程序只创建一次,全局共用. 单例的创建 // SharedPerson.h 文件中 + (instancetype)share; // SharedPerson.m 文件中 static S ...

  8. ios 单例设计模式

    单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类.单例可用性非常高,用于登录用户管理等可供全局调用. + (AccountMa ...

  9. iOS 单例的销毁

    今天做项目的时候,对于不同的用户,需要创建不同的数据库.但是退出登录切换账号时,因为用单例创建数据,导致切换账号不会切换数据.所以,需要销毁单例.销毁单例时,调用以下的代码: 在创建单例的那个类中,调 ...

随机推荐

  1. Python的hasattr(),getattr(),setattr()

    今天读到源码时遇到了setattr()和getattr()两方法,给忘了,重新回顾一下吧! 1. hasattr(object, name) 判断object里是否有name属性,有就返回True,没 ...

  2. SAS 评分卡开发模型变量统计及输出

    以下代码实现功能: 1.获取10个模型分别使用哪些变量 2.变量所模型使用的次数 3.把上表格输出到EXCEL中 %INCLUDE '00@HEADER.SAS'; %let dir=..\04@Mo ...

  3. Window10下安装sbt

    参考:https://segmentfault.com/a/1190000002474507 下载:https://dl.bintray.com/sbt/native-packages/sbt/0.1 ...

  4. Using a ScrollView - RN4

    使用滚动条. 1. import import {ScrollView} from "react-native"; 2. Using <ScrollView> ... ...

  5. Oracle 查询合并列

    在ORACLE  查询时,有时要将多个列合并成一行,其方法如下: 1. decode 函数 decode 函数的语法为: decode(条件,值1,返回值1,值2,返回值2,...值n,返回值n,缺省 ...

  6. linux如何复制文件夹和移动文件夹

    linux下文件的复制.移动与删除命令为:cp,mv,rm一.文件复制命令cp 命令格式:cp [-adfilprsu] 源文件(source) 目标文件(destination)cp [option ...

  7. win10 64位,家庭版,C++,ini配置说明

      #include<windows.h> #include<iostream> #include <atlstr.h> using namespace std; ...

  8. leetcode234

    /** * Definition for singly-linked list. * public class ListNode { * public int val; * public ListNo ...

  9. 前端-toggleClass(效果切换,如果存在移除,如果不存在展示)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  10. 转: rem与px的转换

    rem是相对于根元素<html>,这样就意味着,我们只需要在根元素确定一个参考值,这个参考值设置为多少,完全可以根据您自己的需求来定.· 我们知道,浏览器默认的字号16px,来看一些px单 ...