加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 业界 > 正文

iOS多线程开拓:几个轻易被忽略的细节

发布时间:2019-06-08 21:46:56 所属栏目:业界 来源:Eternal_Love
导读:一样平常环境下,iOS开拓者只要会行使GCD、@synchronized、NSLock等几个简朴的API,就可以应对大部门多线程开拓了,不外这样是否真正做到了多线程安详,又是否真正充实操作了多线程的服从上风呢?看看以下几个轻易被忽略的细节。 读者写者题目(Readers-writers

(2)串行行列上没须要行使GCD barrier,应该行使dispatch_queue_create成立的并刊行列;dispatch_get_global_queue因为是全局共享行列,行使barrier达不到断绝当前使命的结果,会自动降级为dispatch_sync / dispatch_async。[5]

锁的粒度(Granularity)

起首看两段代码:

代码段1

  1. @property (atomic, copy) NSString *atomicStr; 
  2.  
  3. //thread A 
  4. atomicSr = @"am on thread A"; 
  5. NSLog(@"%@", atomicStr); 
  6.  
  7. //thread B 
  8. atomicSr = @"am on thread B"; 
  9. NSLog(@"%@", atomicStr); 

代码段2

  1. - (void)synchronizedAMethod { 
  2.     @synchronized (self) { 
  3.         ... 
  4.     } 
  5.  
  6. - (void)synchronizedBMethod { 
  7.     @synchronized (self) { 
  8.         ... 
  9.     } 
  10.  
  11. - (void)synchronizedCMethod { 
  12.     @synchronized (self) { 
  13.         ... 
  14.     } 

粒渡过小

执行代码段1,在线程A上打印出来的字符串却也许是“am on thread B”,缘故起因是固然atomicStr是原子操纵,可是取出atomicStr之后,在执行NSLog之前,atomicStr如故也许会被线程B修改。因此atomic声明的属性,只能担保属性的get和set是完备的,可是却不能担保get和set完之后的关于该属性的操纵是多线程安详的,这就是aomic声明的属性不必然能担保多线程安详的缘故起因。

同样的,不只仅是atomic声明的属性,在开拓中本身加的锁假如粒度太小,也不能担保线程安详,代码段1着实和下面代码结果同等:

  1. @property (nonatomic, strong) NSLock *lock; 
  2. @property (nonatomic, copy) NSString *atomicStr; 
  3.  
  4. //thread A 
  5. [_lock lock]; 
  6. atomicSr = @"am on thread A"; 
  7. [_lock unlock]; 
  8. NSLog(@"%@", atomicStr); 
  9.  
  10. //thread B 
  11. [_lock lock]; 
  12. atomicSr = @"am on thread B"; 
  13. [_lock unlock]; 
  14. NSLog(@"%@", atomicStr); 

假如想让措施凭证我们的初志,配置完atomicStr后打印出来的就是配置的值,就必要加大锁的范畴,将NSLog也包罗在临界区内:

  1. //thread A 
  2. [_lock lock]; 
  3. atomicSr = @"am on thread A"; 
  4. NSLog(@"%@", atomicStr); 
  5. [_lock unlock]; 
  6.  
  7. //thread B 
  8. [_lock lock]; 
  9. atomicSr = @"am on thread B"; 
  10. NSLog(@"%@", atomicStr); 
  11. [_lock unlock]; 

示例代码很简朴,很轻易看出题目地址,可是在现实开拓中碰着更伟大些的代码块时,一不警惕就也许踏入坑里。因此在计划多线程代码时,要出格留意代码之间的逻辑相关,若后续代码依靠于加锁部门的代码,那这些后续代码也应该一并插手锁中。

粒渡过大

@synchronized要害字会自动按照传入工具建设一个与之关联的锁,在代码块开始时自动加锁,并在代码块竣事后自动解锁,语法简朴明白,很利便行使,可是这也导致部门开拓者过渡依靠于@synchronized要害字,滥用@synchronized(self)。如上述代码段2中的写法,在一整个类文件里,全部加锁的处所用的都是@synchronized(self),这就也许会导致不相干的线程执行时都要相互守候,本来可以并发执行的使命不得不串行执行。其它行使@synchronized(self)还也许导致死锁:

  1. //class A 
  2.  
  3. @synchronized (self) { 
  4.     [_sharedLock lock]; 
  5.     NSLog(@"code in class A"); 
  6.     [_sharedLock unlock]; 
  7.  
  8. //class B 
  9. [_sharedLock lock]; 
  10. @synchronized (objectA) { 
  11.     NSLog(@"code in class B"); 
  12. [_sharedLock unlock]; 

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读