iOS 中关于@synchronized的一点思考
2017-11-24 18:34
267 查看
参考 :
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()通过对一段代码的使用进行加锁。其他试图执行该段代码的线程都会被阻塞,直到加锁线程退出执行该段被保护的代码段
相关术语:
线程同步:多天线程在同一条线上执行(按顺序的执行任务)
互斥锁就是使用了线程同步技术
下面看互斥锁使用格式
锁定一份代码只能用一把锁,多把锁是无效的。
优点:防止多线程操作时资源竞争导致的数据安全问题
缺点:需要消耗大量的CPU资源
互斥锁的使用前提是:多条线程使用同一份资源。
查看该段的汇编代码可知主要使用了两个函数
查看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不会死锁,类似下面的代码还是会导致死锁的
使用同一个token来同步arrA和arrB的访问,虽然arrA和arrB之间没有任何联系。传入self的就更不对了。
应该是不同的数据使用不同的锁,尽量将粒度控制在最细的程度。上述代码应该是:
@synchronized(nil)不起任何作用,所以传参时还是需要做好判断
注意内部的函数调用
在 doSomething:中可能有更多的函数调用,这样就会导致@synchronized更慢,所以建议@synchronized内加锁的代码还是尽量简单的好,
如果无法避免,还是要做好维护工作
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_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; }
查看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 (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)不起任何作用,所以传参时还是需要做好判断
注意内部的函数调用
在 doSomething:中可能有更多的函数调用,这样就会导致@synchronized更慢,所以建议@synchronized内加锁的代码还是尽量简单的好,
如果无法避免,还是要做好维护工作
相关文章推荐
- 关于XSS的一点思考
- 关于为什么要使用脚本引擎与脚本的一点思考
- 关于iOS中MVC和MVVM的一些思考
- 关于白盒测试之基本路径测试法的一点思考
- 【Java基础】关于final修饰符的一点思考
- 详解关于iOS内存管理的规则思考
- 关于新型能源的一点思考.
- 关于算法的一点思考。。。
- 关于找机器学习实习的一点思考
- 关于xml学习的一点思考与总结
- 关于构建自己的知识体系架构的一点个人思考(转载)
- 关于程序员成长的一点思考,程序员必须得看。
- 关于系统的一点思考
- 路要怎么走?关于程序员成长的一点思考
- 关于使用线程池造成tomcat进程无法正常退出的一点思考
- IOS: 状态栏提示控件的实现原理UIWindowLevel详解关于UIWindow的一点儿思考
- 关于交大二手市场的一点思考
- 关于静态方法为什么不能被重写的一点思考以及overload的一些坑。
- 对关于iOS图片压缩的一点积累
- 关于技术提升的一点思考