iOS 中关于@synchronized的一点思考
来源:互联网 发布:股票交易数据分析 编辑:程序博客网 时间:2024/06/05 17:59
参考 :
https://www.cnblogs.com/jukaiit/p/5570056.html
https://www.cnblogs.com/CoderAlex/p/5257339.html
http://www.cocoachina.com/ios/20161205/18279.html
http://www.jianshu.com/p/1e59f0970bf5
首先我们知道@synchronized 的作用是创建一个互斥锁,保证此时没有其它线程对锁对象进行修改。这个是objective-c的一个锁定令牌,防止锁对象在同一时间内被其它线程访问,起到线程的保护作用。
指令@synchronized()通过对一段代码的使用进行加锁。其他试图执行该段代码的线程都会被阻塞,直到加锁线程退出执行该段被保护的代码段
相关术语:
线程同步:多天线程在同一条线上执行(按顺序的执行任务)
互斥锁就是使用了线程同步技术
下面看互斥锁使用格式
@synchronized (锁对象) { 加锁代码 }
锁定一份代码只能用一把锁,多把锁是无效的。
优点:防止多线程操作时资源竞争导致的数据安全问题
缺点:需要消耗大量的CPU资源
互斥锁的使用前提是:多条线程使用同一份资源。
查看该段的汇编代码可知主要使用了两个函数
_objc_sync_enter _objc_sync_exit在Objective-C 中查看源码
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_ERRORint 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;}
查看SyncData
typedef struct SyncData { struct SyncData* nextData; DisguisedPtr<objc_object> object; int32_t threadCount; // number of THREADS using this block recursive_mutex_t mutex;} SyncData;
可见在SyncData 维护了一个递归锁,所以如下代码就不会死锁。
@synchronized (obj) { NSLog(@"13qw"); @synchronized (obj) { NSLog(@"2asda"); }}
但是并不意味着synchronized不会死锁,类似下面的代码还是会导致死锁的
@synchronized (self) { [_sharedLock lock]; NSLog(@"code in class A"); [_sharedLock unlock];}
正确使用@synchronized还需要注意粒度控制
@synchronized (token) { [arrA addObject:obj];}@synchronized (token) { [arrB addObject:obj];}
使用同一个token来同步arrA和arrB的访问,虽然arrA和arrB之间没有任何联系。传入self的就更不对了。
应该是不同的数据使用不同的锁,尽量将粒度控制在最细的程度。上述代码应该是:
@synchronized (tokenA) { [arrA addObject:obj];}@synchronized (tokenB) { [arrB addObject:obj];}
@synchronized(nil)不起任何作用,所以传参时还是需要做好判断
注意内部的函数调用
@synchronized (tokenA) {
[arrA addObject:obj];
[self doSomething:arrA];
}
如果无法避免,还是要做好维护工作
阅读全文
0 0
- iOS 中关于@synchronized的一点思考
- 多线程中关于synchronized的一点事
- 关于Java中static的一点思考
- 关于 && 的一点思考
- 关于计算机体系结构的一点思考。
- 关于计算机体系结构的一点思考
- 关于继承的一点思考
- 关于盗版的一点思考
- 关于宏的一点思考
- 关于计算机的一点思考
- 关于编程的一点思考
- 关于软件设计的一点思考
- 关于string的一点思考
- 关于makefile的一点思考
- 关于“概念”的一点思考
- 关于重载的一点思考
- 关于XSS的一点思考
- 关于code的一点思考
- Lintcode162 Set Matrix Zeroes solution 题解
- 红黑树 修复
- 数据库保护
- linux系统上搭建Hbase分布式集群
- angular2假数据
- iOS 中关于@synchronized的一点思考
- git撤销的方法
- Msql 批量数据判断唯一索引不存在做insert存在做update
- android开发伪两年经验的建议
- 运营活动
- BZOJ 2565 最长双回文串
- GitHub应用
- JAVA常用的集合转换
- 快学Scala-变量声明、常用类型、条件与块表达式、循环、方法函数的调用