@property修饰符种类

@property修饰符种类
 
当我们定义一个字符串属性时,通常我们会这样写:
@property (nonatomic, copy) NSString *name;
复制代码
当我们定义一个NSMutableArray类型的属性时,通常我们会这样写:
@property (nonatomic, strong) NSMutableArray *books;
复制代码
而当我们定一个基本数据类型时,会这样写:
@property (nonatomic, assign) int age;
复制代码
定义一个属性时,nonatomic、copy、strong、assign等被称作是关键字,或者是修饰符。

修饰符种类

修饰符有四种:
  1. 原子性。原子性有nonatomic、atomic两个值,如果不写nonatomic,那么默认是atomic的。如果属性是atomic的,那么在访问其getter和setter方法之前,会有一些判断,大概是判断是否可以访问等,这里系统使用的是自旋锁。由于使用atomic并不能绝对保证线程安全,且会耗费一些性能,因此通常情况下都使用nonatomic。
  2. 读写权限。读写权限有两个取值,readwrite和readonly。声明属性时,如果不指定读写权限,那么默认是readwrite的。如果某个属性不想让其他人来写,那么可以设置成readonly。
  3. 内存管理。内存管理的取值有assign、strong、weak、copy、unsafe_unretained。
  4. set、get方法名。如果不想使用自动合成所生成的setter、getter方法,声明属性时甚至可以指定方法名。比如指定getter方法名:
@property (nonatomic, assign, getter=isPass) BOOL pass;
复制代码
属性pass的getter方法就是
- (BOOL)isPass;
复制代码

默认修饰符

声明属性时,如果不显示指定修饰符,那么默认的修饰符是哪些呢?或者说未指定的修饰符,默认取值是什么呢?
如果是基本数据类型,默认取值是:atomic,readwrite,assign
 
如果是Objective-C对象,默认取值是:atomic,readwrite,strong
 

atomic是否是线程安全的

上面提到了,声明属性时,通常使用nonatomic修饰符,原因就是因为atomic并不能保证绝对的线程安全。举例来说:
单独的原子操作绝对是线程安全的,但是组合一起的操作就不能保证。
 1 - (void)competition {
 2 self.intSource = 0;
 3  
 4 dispatch_async(queue1, ^{
 5 for (int i = 0; i < 10000; i++) {
 6 self.intSource = self.intSource + 1;
 7 }
 8 });
 9  
10 dispatch_async(queue2, ^{
11 for (int i = 0; i < 10000; i++) {
12 self.intSource = self.intSource + 1;
13 }
14 });
15 }
最终得到的结果肯定小于20000。当获取值的时候都是原子线程安全操作,比如两个线程依序获取了当前值 0,于是分别增量后变为了 1,所以两个队列依序写入值都是 1,所以不是线程安全的。
所以 atomic通过这种方法,在运行时保证 set,get方法的原子性。仅仅是保证了set,get方法的原子性。
但是self.intA = self.intA + 1这个表达式并不是原子操作。所以线程是不安全的。所以仅仅使用atomic并不能保证线程安全。

 

解决的办法应该是增加颗粒度,将读写两个操作合并为一个原子操作,从而解决写入过期数据的问题。
 1 objcos_unfair_lock_t unfairLock;
 2 - (void)competition {
 3 self.intSource = 0;
 4  
 5 unfairLock = &(OS_UNFAIR_LOCK_INIT);
 6 dispatch_async(queue1, ^{
 7 for (int i = 0; i < 10000; i++) {
 8 os_unfair_lock_lock(unfairLock);
 9 self.intSource = self.intSource + 1;
10 os_unfair_lock_unlock(unfairLock);
11 }
12 });
13  
14 dispatch_async(queue2, ^{
15 for (int i = 0; i < 10000; i++) {
16 os_unfair_lock_lock(unfairLock);
17 self.intSource = self.intSource + 1;
18 os_unfair_lock_unlock(unfairLock);
19 }
20 });
21 }
在接下来的文章里会分别去讲解用法

 

原文地址:https://www.cnblogs.com/junhuawang/p/13529751.html