重学OC第二十一篇:@synchronized分析

本文详细分析了Objective-C中的@synchronized关键字,探讨了它如何通过objc_sync_enter和objc_sync_exit实现线程同步。文章重点解析了objc_sync_enter源码,特别是id2data()函数,介绍了SyncData、SyncCacheItem等结构体,并指出当线程过多时,链表查询可能变得耗时。同时,文章还介绍了objc_sync_exit的解锁过程,指出@synchronized采用递归互斥锁并利用TLS存储缓存。
摘要由CSDN通过智能技术生成

一、clang分析@synchronized

int main(int argc, const char * argv[]) {
   
  	NSObject *obj = [[NSObject alloc] init];
    @synchronized (obj) {
   
    }
    return 0;
}

通过clang -rewrite-objc main.m转为main.cpp后@synchronized (obj) { }内容如下

{
   
    id _rethrow = 0;
    id _sync_obj = (id)obj;
    objc_sync_enter(_sync_obj);
    try {
   
        struct _SYNC_EXIT {
   
            _SYNC_EXIT(id arg) : sync_exit(arg) {
   }  //构造函数,通过arg初始化sync_exit
            ~_SYNC_EXIT() {
   objc_sync_exit(sync_exit);} //析构函数
            id sync_exit;
        } _sync_exit(_sync_obj);  //把_sync_obj通过构造函数赋值给了sync_exit,它的生命周期是在try中,try执行完就会走析构调用objc_sync_exit
    } catch (id e) {
   
        _rethrow = e;
    }

    {
   
        struct _FIN {
   
            _FIN(id reth) : rethrow(reth) {
   }
            ~_FIN() {
    if (rethrow) objc_exception_throw(rethrow); }
            id rethrow;
        } _fin_force_rethow(_rethrow);
    }
}

可以看到主要是内容包括一个objc_sync_enter和一个try-catch-finally结构,重点关注try中的内容,通过_sync_exit(_sync_obj)初始化了一个sync_exit = _sync_obj的struct _SYNC_EXIT结构体对象,然后在try作用域执行完后调用它的析构函数自运执行objc_sync_exit。那么可以看出@synchronized (obj) { }主要就是对obj进行objc_sync_enter和objc_sync_exit操作,以及抛出异常。

二、objc_sync_enter()源码解析

打上符号断点objc_sync_enter,找到objc_sync_enter属于libobjc.A.dylib,查看objc中objc_sync_enter源码。

//开始在obj上进行同步。如果有需要,会分配与obj关联的递归互斥锁。一旦获取锁成功返回OBJC_SYNC_SUCCESS。
int objc_sync_enter(id obj)
{
   
    int result = OBJC_SYNC_SUCCESS;  //OBJC_SYNC_SUCCESS=0
    if (obj) {
   
        SyncData* data = id2data(obj, ACQUIRE);
        ASSERT(data);
        //加锁
        data->mutex.lock();
    } else {
   
        // @synchronized(nil) does nothing
        if (DebugNilSync) {
   
            _objc_inform("NIL SYNC DEBUG: @synchronized(nil); set a breakpoint on objc_sync_nil to debug");
        }
        //啥也不干,asm("");
        objc_sync_nil();
    }
    return result;
}

通过上面代码可以看到如果obj存在,通过id2data()函数拿到了data,调用data的mutex进行加锁。如果obj为nil,objc_sync_enter什么也不做。

2.1 id2data()函数分析

在看id2data()函数前,先来了解下其中用到的SyncData、SyncCacheItem、SyncCache、SyncList结构体。

struct SyncList {
   
    SyncData *data;
    spinlock_t lock;

    constexpr SyncList
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值