这个问题很少遇到,但是答案当然不是。
atomic在set方法里加了锁,防止了多线程一直去写这个property,造成难以预计的数值。但这也只是读写的锁定。跟线程安全其实还是差一些。看下面。
@interface MONPerson : NSObject
@property (copy) NSString * firstName;
@property (copy) NSString * lastName;
- (NSString *)fullName;
@end
Thread A:
p.firstName = @"Rob";
Thread B:
p.firstName = @"Robert";
Thread A:
label.string = p.firstName; // << uh, oh -- will be Robert
但是如果有个C也在写,D在读取,D会读到一些随机的值(ABC修改的值),这就不是线程安全的了。最好的方法是使用lock。
Thread A:
[p lock]; // << wait for it… … … …
// Thread B now cannot access
pp.firstName = @"Rob";
NSString fullName = p.fullName;
[p unlock];
// Thread B can now access plabel.string = fullName;
Thread B:
[p lock]; // << wait for it… … … …
// Thread A now cannot access p…
[p unlock];
atomic有个很大的问题是很慢,要比nonatomic慢20倍。
当然最后建议这种数值数值变化可以让服务器来做。
网友评论
何谓线程安全,线程安全就是在保证读写在多线程下串行执行。
这题问的应该是为什么在多线程情况下我们不用atomic。
因为如有三个及以上的线程访问同一资源,atomic并不能保证程序的一致性。
因为线程安全只能保证临界区不在多线程下同时执行,但是
三个线程还牵扯到先来后到的问题,这已经不是线程安全问题了。
比如A读取,B,C写入,假如B先执行,而A,C到底谁先来会影响A的值的。
所以既然无论如何都无法保证程序的一致性,那么用atomic反而会增加
程序负担,还不如不如。对于并发问题,让程序员自己去解决。
简而言之,就是我做的已经没问题了,但是你用的有问题我仍然无法保证,
那么干脆别用,得不偿失。
我们知道,在64位的操作系统下,所有类型的指针,包括void * 都是占用8个字节的。超过4个字节的基本类型数据都会有线程并发的问题。
那所有的指针类型都会有这个问题。
以oc 下的 NSArray * 为例子,如果一个多线程操作这个数据,会有两个层级的并发问题
1、指针本身
2、指针所指向的内存
指针本身也是占用内存的,并且一定是8个字节,第二部分,指针所指向的内存,这个占多少字节就不一定了,有可能非常大,有可能也就1个字节
所以我们考虑NSArray * array 这个数据array 多线程操作的时候,必须分成两部分来描述,一个是&array这个指针本身,另一个则是它所指向的内存 array
大家注意下 &array 和 array 的区别 ,其实不用纠结,你就想象现在有两块内存,一块是8字节,一块n字节,8字节里面放的值,就是n字节内存的首地址,
ok 现在联系上atomic,如果用@property(atomic)NSArray *array 修饰之后,会有什么影响?网上说的很多,不再赘述,我只想从内存的角度来解释这个过程
首先第一点,你要记住,@property(atomic)NSArray *array 其实修饰的是这个指针,也就是这个8字节内存,跟第二部分数据n字节没有任何关系,被atomic 修饰之后,你不可能随意去多线程操作这个8字节,但是对8字节里面所指向的n字节没有任何限制!这就是所有网络上所说的 atomic 不安全的真相 !!!
我们来看一下,这能怪atomic? 本身你修饰的是一个指针,并且atomic 已经完美的履行了它的指责,你现在不可能对这个8字节进行无序的多线程操作,这就够了呀!atomic没有任何鸟问题。有问题的是人,你本身并未对n字节做任何的限制,所以把问题怪罪到atomic 上真的是很不合理