博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于@synchronized
阅读量:5331 次
发布时间:2019-06-14

本文共 3963 字,大约阅读时间需要 13 分钟。

一、结论

  1)@synchronized内部使用的是recursive_mutex_lock,也就是递归锁,对于统一线程来说,@synchronized加锁的方法可以重复加锁。

  比如代码:

  

- (void)viewDidLoad {    [super viewDidLoad];    // Do any additional setup after loading the view, typically from a nib.    [self testA];}- (void)testA{    @synchronized(self)    {        NSLog(@"AAAAAA");        [self testB];    }}- (void)testB{    @synchronized(self)    {        NSLog(@"BBBBBB");    }}

   输出结果为:

  

2018-08-21 15:25:51.058333+0800 TestSynchronized2[17367:7864821] AAAAAA2018-08-21 15:25:51.058372+0800 TestSynchronized2[17367:7864821] BBBBBB

  

  2)@synchronized 可以看成一个函数,加锁的对象是后面传入对象的地址,所以如果加锁对象重新赋值,那么地址会重新该表导致加锁失效。

     如果这个对象为nil,那么等于没有加锁。

    内部实现源代码如下:

    

static void _I_Demo_synchronizedTest(Demo * self, SEL _cmd) {     NSMutableArray *arr;     {      id _sync_obj = (id)arr;      objc_sync_enter(_sync_obj); // 同步锁进入,参数是arr         try {             struct _SYNC_EXIT {                _SYNC_EXIT(id arg) : sync_exit(arg) {}                  ~_SYNC_EXIT() {objc_sync_exit(sync_exit); // 同步锁退出,参数是arr   }             id sync_exit;        }   _sync_exit(_sync_obj);// 调用结构体的构造函数,参数是arr           } catch (id e) {       }    }}int objc_sync_enter(id obj)    {               int result = OBJC_SYNC_SUCCESS;              if (obj) {            // 根据obj获取对应的SyncData节点,id2data函数在下面有解析            SyncData* data = id2data(obj, ACQUIRE);// 上锁             result = recursive_mutex_lock(&data->mutex); }         else           { // @synchronized(nil) does nothing     }       return result;    }typedef struct SyncData {             struct SyncData* nextData; // 指向下一个SyncData节点的指针             DisguisedPtr
object; // @synchronized的参数obj int32_t threadCount; // number of THREADS using this block recursive_mutex_t mutex; // 递归锁 } SyncData; struct SyncList { SyncData *data; // 单链表头指针 spinlock_t lock; // 保证多线程安全访问该链表 SyncList() : data(nil) { } };static StripedMap
sDataLists; // 哈希表,key:obj,value:单链表 // 根据obj获取对应的SyncData节点static SyncData* id2data(id object, enum usage why) { spinlock_t *lockp = &LOCK_FOR_OBJ(object); // SyncList锁 SyncData **listp = &LIST_FOR_OBJ(object); // obj对应的SyncData节点所在的 SyncList SyncData* result = NULL;// 这里省略一大坨cache代码 lockp->lock(); { SyncData* p; SyncData* firstUnused = NULL; // 遍历单链表 for (p = *listp; p != NULL; p = p->nextData) { if ( p->object == object ) { // 找到obj对应的SyncData节点 result = p; // SyncData节点对应的线程数加1 OSAtomicIncrement32Barrier(&result->threadCount); goto done; } // SyncData节点对应的递归锁没有线程在用了,回收重用,可以节省节点创建的时间和空间 if ( (firstUnused == NULL) && (p->threadCount == 0) ) firstUnused = p; } // 链表中还没有obj对应的SyncData节点,但是有可重用的SyncData节点 // an unused one was found, use it if ( firstUnused != NULL ) { result = firstUnused; result->object = (objc_object *)object; result->threadCount = 1; goto done; } }// 链表中还没有obj对应的SyncData节点,而且没有可重用的SyncData节点 result = (SyncData*)calloc(sizeof(SyncData), 1); result->object = (objc_object *)object; result->threadCount = 1; new (&result->mutex) recursive_mutex_t();// 新建的SyncData节点往链表头部加 result->nextData = *listp; *listp = result; done: lockp->unlock(); return result;}

  

  3)swift中没有对应的方法,但是依然可以使用OC中调用加锁的函数,实现如下

  

func synchronized
(_ lock: AnyObject, _ body: () throws -> T) rethrows -> T { objc_sync_enter(lock) defer { objc_sync_exit(lock) } return try body() }

  

 

参考资料:

  作者:悲观患者

  链接:https://www.jianshu.com/p/d83b3b7d5a5a

    

转载于:https://www.cnblogs.com/doudouyoutang/p/9511713.html

你可能感兴趣的文章
介绍Win7 win8 上Java环境的配置
查看>>
Linux设置环境变量的方法
查看>>
构建自己的项目管理方案
查看>>
利用pca分析fmri的生理噪声
查看>>
div水平居中且垂直居中
查看>>
epoll使用具体解释(精髓)
查看>>
AndroidArchitecture
查看>>
安装Endnote X6,但Word插件显示的总是Endnote Web"解决办法
查看>>
python全栈 计算机硬件管理 —— 硬件
查看>>
大数据学习
查看>>
简单工厂模式
查看>>
Delphi7编译的程序自动中Win32.Induc.a病毒的解决办法
查看>>
Objective-C 【关于导入类(@class 和 #import的区别)】
查看>>
倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-点击运行按钮进入到运行状态报错Error starting TwinCAT System怎么办 AdsWarning1823怎么办...
查看>>
【转】javascript 中的很多有用的东西
查看>>
Android 监听返回键、HOME键
查看>>
Android ContentProvider的实现
查看>>
sqlserver 各种判断是否存在(表名、函数、存储过程等)
查看>>
给C#学习者的建议 - CLR Via C# 读后感
查看>>
Recover Binary Search Tree
查看>>