单例

单例:

单例指一个唯一的,由全局共享的对象,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类

static A* g_ aObj=nil; (静态的模块变量)
满足单例的条件: 在整个程序的运行期间A类的对象的个数始终小于等于1
满足对象条件:1.有一块内存 2.对象是被初始化了的(只要把初始化函数设置为私有的方法,外界就不会任意的创建出单例对象了,属于第二个方法)
OC的解决办法:通过allocWithZone这个类方法,当用户反复调用alloc函数的时候,系统自动调用allocWithZone这个类方法,从而保证了只有一个单例对象(即限制了内存,属于对象的第一个方法,即用户获得的还是已经存在的单例的那块内存,alloc是失败的)

+(id)allocWithZone:(struct _NSZone *)zone //非线程安全的
{
   if(g_aObj==nil)
   {
     g_aObj=[super  allocWithZone:zone];
   } 
   return  g_aObj;
}

单例的线程安全问题:

如果有两个线程同时调用allocWithZone这个方法,线程a调用这个方法,当确认单例为nil的时候,系统把时间片切换给线程b,b这里单例也是nil,这样就会有两个单例,不满足但离得条件,所以加一个互斥锁从而达到线程安全的目的
//上锁

 if(g_aObj==nil)
   {
     g_aObj=[super  allocWithZone:zone];
   } 
   return  g_aObj;

//开锁
但是这样会有一个问题:每次调用都要上锁开锁(上开锁会有一定的性能损失,上锁开锁只有在A对象第一次实例化的时候起作用,A对象创建好之后就会远远存在内存中,if语句永远不成立,就不用再反复地上锁开锁)解决办法: double check机制

if(g_aObj==nil)
{ 
    //上锁
     if(g_aObj==nil)
     {
       g_aObj=[super  allocWithZone:zone];
     } 
    //开锁  
}  
 return  g_aObj;

double check机制等同于下面的方法:

   if(g_aObj==nil)
   {
       @synchronized(g_aObj)
       g_aObj=[super  allocWithZone:zone];

   } 
   return  g_aObj;

解决方法2:
第一次调用某个类的+函数的时候,在这之前就会调用这个函数,第二次在调用+函数的时候就不会再调用这个方法(特有的单例免锁写法,同时是线程安全的)
+(void)initialize
{
g_aObj=[[A alloc]init];
}

下面是一个完整的单例的写法

@class A;
static  A* g_aObj=nil;
@interface A:NSObject
{
 @public
    int   _a;
}
@end
@implementation   A
+(A*)shareAObj
{
   if(g_aObj == nil)
   {
          @synchronized(g_aObj)
          {
                 if(g_aObj == nil)
                 {
                     g_aObj=[[A alloc]init];
                 }
           }
   }
   return g_aObj;
}
+(id)allocWithZone:(struct _NSZone *)zone
{
     if(g_aObj == nil)
    {
          @synchronized(g_aObj)
          {
              g_aObj=[super  allocWithZone:zone];
          }
     }
    return  g_aObj;
}
+(id)copyWithZone:(struct _NSZone *)zone
{
   return g_aObj;
}

-(id)retain
{
return self;
}
-(id)autorelease
{
  return self;
}
-(NSUInteger)retainCount
{
   return  UINT_MAX;
}
-(void)release
{
   //do nothing
}
@end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值