iOS多线程开发:几个容易被忽略的细节
(2)串行队列上没必要使用GCD barrier,应该使用dispatch_queue_create建立的并发队列;dispatch_get_global_queue由于是全局共享队列,使用barrier达不到隔离当前任务的效果,会自动降级为dispatch_sync / dispatch_async。[5] 锁的粒度(Granularity) 首先看两段代码: 代码段1
代码段2
粒度过小 执行代码段1,在线程A上打印出来的字符串却可能是“am on thread B”,原因是虽然atomicStr是原子操作,但是取出atomicStr之后,在执行NSLog之前,atomicStr仍然可能会被线程B修改。因此atomic声明的属性,只能保证属性的get和set是完整的,但是却不能保证get和set完之后的关于该属性的操作是多线程安全的,这就是aomic声明的属性不一定能保证多线程安全的原因。 同样的,不仅仅是atomic声明的属性,在开发中自己加的锁如果粒度太小,也不能保证线程安全,代码段1其实和下面代码效果一致:
如果想让程序按照我们的初衷,设置完atomicStr后打印出来的就是设置的值,就需要加大锁的范围,将NSLog也包括在临界区内:
示例代码很简单,很容易看出问题所在,但是在实际开发中遇到更复杂些的代码块时,一不小心就可能踏入坑里。因此在设计多线程代码时,要特别注意代码之间的逻辑关系,若后续代码依赖于加锁部分的代码,那这些后续代码也应该一并加入锁中。 粒度过大 @synchronized关键字会自动根据传入对象创建一个与之关联的锁,在代码块开始时自动加锁,并在代码块结束后自动解锁,语法简单明了,很方便使用,但是这也导致部分开发者过渡依赖于@synchronized关键字,滥用@synchronized(self)。如上述代码段2中的写法,在一整个类文件里,所有加锁的地方用的都是@synchronized(self),这就可能会导致不相关的线程执行时都要互相等待,原本可以并发执行的任务不得不串行执行。另外使用@synchronized(self)还可能导致死锁:
(编辑:PHP编程网 - 黄冈站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |