(2)串行队列上没必要使用GCD barrier,应该使用dispatch_queue_create建立的并发队列;dispatch_get_global_queue由于是全局共享队列,使用barrier达不到隔离当前任务的效果,会自动降级为dispatch_sync / dispatch_async。[5]
锁的粒度(Granularity)
首先看两段代码:
代码段1
- @property (atomic, copy) NSString *atomicStr;
-
- //thread A
- atomicSr = @"am on thread A";
- NSLog(@"%@", atomicStr);
-
- //thread B
- atomicSr = @"am on thread B";
- NSLog(@"%@", atomicStr);
代码段2
- - (void)synchronizedAMethod {
- @synchronized (self) {
- ...
- }
- }
-
- - (void)synchronizedBMethod {
- @synchronized (self) {
- ...
- }
- }
-
- - (void)synchronizedCMethod {
- @synchronized (self) {
- ...
- }
- }
粒度过小
执行代码段1,在线程A上打印出来的字符串却可能是“am on thread B”,原因是虽然atomicStr是原子操作,但是取出atomicStr之后,在执行NSLog之前,atomicStr仍然可能会被线程B修改。因此atomic声明的属性,只能保证属性的get和set是完整的,但是却不能保证get和set完之后的关于该属性的操作是多线程安全的,这就是aomic声明的属性不一定能保证多线程安全的原因。
同样的,不仅仅是atomic声明的属性,在开发中自己加的锁如果粒度太小,也不能保证线程安全,代码段1其实和下面代码效果一致:
- @property (nonatomic, strong) NSLock *lock;
- @property (nonatomic, copy) NSString *atomicStr;
-
- //thread A
- [_lock lock];
- atomicSr = @"am on thread A";
- [_lock unlock];
- NSLog(@"%@", atomicStr);
-
- //thread B
- [_lock lock];
- atomicSr = @"am on thread B";
- [_lock unlock];
- NSLog(@"%@", atomicStr);
如果想让程序按照我们的初衷,设置完atomicStr后打印出来的就是设置的值,就需要加大锁的范围,将NSLog也包括在临界区内:
- //thread A
- [_lock lock];
- atomicSr = @"am on thread A";
- NSLog(@"%@", atomicStr);
- [_lock unlock];
-
- //thread B
- [_lock lock];
- atomicSr = @"am on thread B";
- NSLog(@"%@", atomicStr);
- [_lock unlock];
(编辑:西安站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|