iOS Synchronized的内部实现原理

任何时候探究一些原理都得从源码抓起 objc_sync

关于@synchronized,

使用场景一:写单例的时候,

使用场景二:在多线程的情况下,进行加锁操作.

那么锁是如何传入@synchronized的对象关联上的?✨✨✨✨✨✨

如果传入@synchronized的对象在@synchronized的block里面被释放或者被赋值为nil会怎样?✨✨✨✨✨✨

@synchronized block 会变成objc_sync_enter 和 objc_sync_exit成对调用.✨✨✨✨✨✨

✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
@synchronized结构在工作时为传入的对象分配了一个递归锁.

递归锁在被同一线程重复获取时不会产生死锁.你可以在这找到一个它工作原理的精巧案例.和NSRecursiveLock类似.

在objc-sync的源码中,有一个结构体 struct SyncData,包含了object 就是我们传入的对象和一个关联的recursive_mutex_t, 它就是那个跟object关联在一起的锁.每个SyncData也包含一个指向另一个SyncData对象的指针,叫nextData.所以可以把每个SyncData结构体看做是链表中的一个元素.每个SyncData还包含一个threadCount,这个syncData对象中的锁会被一些线程使用或等待,threadCount就是此时这些线程的数量.syncData结构体会被缓存,threadCount= 0 代表这个syncData实例可以被复用.

Struct SyncList的定义 把SyncData当做是链表中的节点.每个SyncList结构体都有个指向SyncData节点链表头部的指针,也有一个用于防止多个线程对此列表做并发修改的锁.

sDataLists的声明是一个SyncList结构体数组,大小16.通过哈希算法将传入对象映射到数组上的一个下标.✨✨✨✨✨✨

当调用objc_sync_enter(obj)时,用obj内存地址的哈希值查找合适的SyncData,将其上锁.当调用objc_sync_exit(obj),查找合适的SyncData将其解锁 ✨✨✨✨✨✨

总结:

1.当调用synchronzied的每个对象,runtime都会为其分配一个递归锁并存储在哈希表中

2.如果在synchronzied内部对象被释放或为nil,会执行类似objc_sync_nil的空方法

3.不要想synchronzied block 传入nil , 如果为nil ,则将会从代码中线程安全

最后,思考:如何自己实现synchronized锁呢?边看源码边敲寻找灵感

参考链接:https://bestswifter.com/ios-lock/

  pthread_mutex_lock 源码参考

  ThreadSafety

 关于Synchronized

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容