单例的销毁

单例的代码实现

    static Person *ple ;
    static dispatch_once_t predicate;
    
    dispatch_once(&predicate, ^{
        NSLog(@"2:%ld", predicate);
        ple = [[Person alloc] init];
    });
    

单例的底层实现原理

void dispatch_once(dispatch_once_t *val, dispatch_block_t block{
	dispatch_once_f(val, block, _dispatch_Block_invoke(block));
}
void
dispatch_once_f(dispatch_once_t *val, void *ctxt, dispatch_function_t func)
{
	dispatch_once_gate_t l = (dispatch_once_gate_t)val;

#if !DISPATCH_ONCE_INLINE_FASTPATH || DISPATCH_ONCE_USE_QUIESCENT_COUNTER
	uintptr_t v = os_atomic_load(&l->dgo_once, acquire);
        
        // 状态为 DLOCK_ONCE_DONE 直接返回
	if (likely(v == DLOCK_ONCE_DONE)) {
		return;
	}
#if DISPATCH_ONCE_USE_QUIESCENT_COUNTER
	if (likely(DISPATCH_ONCE_IS_GEN(v))) {
		return _dispatch_once_mark_done_if_quiesced(l, v);
	}
#endif
#endif
        // 第一次进来 获取锁, 原子操作多线程处理
	if (_dispatch_once_gate_tryenter(l)) {
                //执行调用
		return _dispatch_once_callout(l, ctxt, func);
	}
        // 有锁锁住的话 会 等待开锁
	return _dispatch_once_wait(l);
}

分析:

  • 1.内部实现的 val (也就是 static dispatch_once_t predicate ) 这个变量用来获取底层原子性的一个关联。关联一个 uintptr_t 类型 v的一个变量,用来查询。
  • 2.当前的 onceToken是一个全局的静态变量。根据每个单利不同,每个静态变量也不同,为了保证唯一性。
  • 3.已经处理过一次了,就retune返回出去了。
  • 4.当第一次代码执行进来的时候:为了保证线程的安全性把自己锁起来,保证当前任务执行的唯一,防止相同的onceToken进行多次执行。锁住之后进行 block 的调用执行。调用完毕后将锁解开,于此同时会将 v 的值 置为 DLOCK_ONCE_DONE(下次就不会在进入到调用block流程)。
    所以保证了单利的唯一性。

如何销毁 ?

通过上面的分析我们可以得到代码执行一次的原因是由于predicate导致,所以当我们销毁的时候也是操作predicate

1.将对应的变量做成全局的变量

//放到外面声明
    static Person *ple ;
    static dispatch_once_t predicate;

2.添加一个类方法:

+ (void)deallocSM {
    predicate = 0;
    per = nil;
}

单例线程安全吗 ?

_dispatch_once_gate_tryenter(l)
static inline bool
_dispatch_once_gate_tryenter(dispatch_once_gate_t l)
{
	return os_atomic_cmpxchg(&l->dgo_once, DLOCK_ONCE_UNLOCKED,
			(uintptr_t)_dispatch_lock_value_for_self(), relaxed);
}

这里是原子操作,并且对线程操作进行加锁处理。_dispatch_lock_value_for_self 是当前队列中的线程空间锁,防止多线程操作 。防止相同的onceToken进行多次执行。线程安全。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值