互斥锁--@synchronized

@synchronized

介绍:@syncheinized也是互斥锁,相比其他锁使用比较简单,只需将临界资源放在@synchronized里面即可,如下

@synchronized (self) {
    [arr addObject:item];//防止不同线程向同时操作数组
}

官方文档中描述@synchronized的block添加了异常处理,有异常时将自动释放互斥量。

实现细节:Xcode编译后@s ynchronized的block会变成objc_sync_enterobjc_sync_exit,objc_sync_enter和objc_sync_exit代替blcok将临界区保护起来,这个成对调用的底层使用递归锁来实现,下面我们分析在runtime源码看一下系统何时怎样分配的递归锁呢?

int objc_sync_enter(id obj)
{
    int result = OBJC_SYNC_SUCCESS;、
    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");
        }
        objc_sync_nil();
    }
    return result;
}

// End synchronizing on 'obj',Returns OBJC_SYNC_SUCCESS or OBJC_SYNC_NOT_OWNING_THREAD_ERROR
int objc_sync_exit(id obj)
{
    int result = OBJC_SYNC_SUCCESS;
    if (obj) {
        SyncData* data = id2data(obj, RELEASE); 
        if (!data) {
            result = OBJC_SYNC_NOT_OWNING_THREAD_ERROR;
        } else {
            bool okay = data->mutex.tryUnlock();
            if (!okay) {
                result = OBJC_SYNC_NOT_OWNING_THREAD_ERROR;
            }
        }
    } else {
        // @synchronized(nil) does nothing
    }
    return result;
}

​ 首先,我们看一下objc_sync_enter方法,这个方法里面创建了一个SyncData对象,并且给SyncData对象分配了一个mutex锁,也就是在进入block时,创建SyncData对象,并且分配递归锁。而SyncData对象的结构如下,它是一个结构体,结构里面的object接收objc_sync_enter传进来的obj,结构里面的mutex是与对象关联的锁,nextData指向另一个SyncData对象的指针,threadCount表示想获取锁的线程,结构体里面的mutex可能被其他线程请求,所以记录一下使请求该锁的线程数;SyncData可看作SyncList链表中的节点, SyncList结构体中data是指向 SyncData节点链表头部的指针,lock是防止多个线程操作SyncLIst列表使用的锁。

typedef struct SyncData {
    id object;
    recursive_mutex_t mutex;
    struct SyncData* nextData;
    int threadCount;
} SyncData;

typedef struct SyncList {
    SyncData *data;
    spinlock_t lock;
} SyncList;

//通过定义的一个哈希算法将传入对象映射到数组上的一个下标。LOCK_FOR_OBJ(obj)和LIST_FOR_OBJ(obj)先是哈希出对象的数组下标,然后取出数组对应元素的lock或data
// Use multiple parallel lists to decrease contention among unrelated objects.
#define LOCK_FOR_OBJ(obj) sDataLists[obj].lock
#define LIST_FOR_OBJ(obj) sDataLists[obj].data
static StripedMap<SyncList> sDataLists;

当你调用 objc_sync_enter(obj)时,它用 obj内存地址的哈希值查找合适的SyncData,然后将其上锁。当你调用objc_sync_exit(obj)时,它查找合适的 SyncData并将其解锁。

参考:关于 @synchronized,这儿比你想知道的还要多

​ https://juejin.im/post/6844904086161063944

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员的修养

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值