【iOS Sharing】【7】属性相关
本文最后更新于:2021年12月22日 中午
【iOS笔记】系列目录
目录
1、atomic关键字内部使用的是什么锁?
2、@property(copy)NSMutableArray *array这样声明属性会出现什么问题?
3、什么情况使用 weak 关键字,相比 assign 有什么不同?
4、weak属性需要在dealloc中置nil么?
5、ARC下,不显式指定任何属性关键字时,默认的关键字都有哪些?
1、atomic关键字内部使用的是什么锁?
答:首先了解一些基本概念:
临界区:指的是一块对公共资源进行访问的代码,并非一种机制或是算法。
自旋锁:是用于多线程同步的一种锁,线程反复检查锁变量是否可用。由于线程在这一过程中保持执行,因此是一种忙等待。一旦获取了自旋锁,线程会一直保持该锁,直至显式释放自旋锁。 自旋锁避免了进程上下文的调度开销,因此对于线程只会阻塞很短时间的场合是有效的。
互斥锁(Mutex):是一种用于多线程编程中,防止两条线程同时对同一公共资源(比如全局变量)进行读写的机制。该目的通过将代码切片成一个一个的临界区而达成。
读写锁:是计算机程序的并发控制的一种同步机制,也称“共享-互斥锁”、多读者-单写者锁) 用于解决多线程对公共资源读写问题。读操作可并发重入,写操作是互斥的。 读写锁通常用互斥锁、条件变量、信号量实现。
信号量(semaphore):是一种更高级的同步机制,互斥锁可以说是semaphore在仅取值0/1时的特例。信号量可以有更多的取值空间,用来实现更加复杂的同步,而不单单是线程间互斥。
条件锁:就是条件变量,当进程的某些资源要求不满足时就进入休眠,也就是锁住了。当资源被分配到了,条件锁打开,进程继续运行。
死锁:指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去,这些永远在互相等待的进程称为死锁进程。
轮询(Polling):一种CPU决策如何提供周边设备服务的方式,又称“程控输出入”。轮询法的概念是,由CPU定时发出询问,依序询问每一个周边设备是否需要其服务,有即给予服务,服务结束后再问下一个周边,接着不断周而复始。
锁的类型:
互斥锁
- NSLock
- pthread_mutex
- pthread_mutex(recursive)递归锁
- @synchronized
自旋锁
- OSSpinLock
- os_unfair_lock
读写锁
- pthread_rwlock
递归锁
NSRecursiveLock
pthread_mutex(recursive)(见上)
条件锁
- NSCondition
- NSConditionLock
信号量
- dispatch_semaphore
1 |
|
atomic使用的是自旋锁,主要用于赋值操作等轻量操作(散列表,引用计数,弱引用指针赋值),而互斥锁一般都是锁线程,比如单例。
OC method简单介绍
1 |
|
objc_method 存储了方法名,方法类型和方法实现。
SEL 方法名类型
方法类型 method_types 是个 char 指针,存储方法的参数类型和返回值类型
method_imp 指向了方法的实现,本质是一个函数指针
Ivar
Ivar 是表示成员变量的类型。
1 |
|
其中 ivar_offset 是基地址偏移字节
IMP
IMP在objc.h中的定义是:
1 |
|
它就是一个函数指针,这是由编译器生成的。当你发起一个 ObjC 消息之后,最终它会执行的那段代码,就是由这个函数指针指定的,而 IMP 这个函数指针就指向了这个方法的实现。
2、@property(copy)NSMutableArray *array这样声明属性会出现什么问题?
答:- NSMutableArray经过copy修饰后是NSArray(不可变数组)。如果对经copy修饰后的可变数组进行增删改的操作,实际上是在操作不可变数组,从而会引起程序异常,引起Crash。
- 不写原子性修饰词默认使用atomic,而atomic性能比nonatomic差很多。
扩展:
浅拷贝:指针拷贝,不生成新对象
- 不可变对象的不可变拷贝
1 |
|
输出:
深拷贝:生成一个新对象,对象内容相同( 除浅拷贝那种情况,其他都是深拷贝)
- 可变对象的可变拷贝
1 |
|
输出:
可变对象的不可变拷贝
1
2
3
4
5
6
7NSMutableArray *mutArray = [NSMutableArray array];
//不同地址
NSLog(@"%p",mutArray);
NSLog(@"%p",[mutArray copy]);
// __NSArray0
NSLog(@"%@",NSStringFromClass([[mutArray copy] class]));输出:
不可变对象的可变拷贝
1 |
|
输出:
总结:
除不可变对象的不可变拷贝为浅拷贝,其余都是深拷贝
3、什么情况使用 weak 关键字,相比 assign 有什么不同?
(1)、什么情况下使用weak:
- 在ARC中修饰代理
- 使用@IBOutlet连接控件
- 当block会造成循环引用
(2)、与assign的不同
assign可以用于非对象类型,而weak必须用于对象类型
进阶
区别
- 修饰变量类型的区别
weak 只可以修饰对象。如果修饰基本数据类型,编译器会报错-“Property with ‘weak’ attribute must be of object type”。
assign 可修饰对象,和基本数据类型。当需要修饰对象类型时,MRC时代使用unsafe_unretained。当然,unsafe_unretained也可能产生野指针,所以它名字是”unsafe_”。
- 是否产生野指针的区别
weak 不会产生野指针问题。因为weak修饰的对象释放后(引用计数器值为0),指针会自动被置nil,之后再向该对象发消息也不会崩溃。 weak是安全的。
assign 如果修饰对象,会产生野指针问题;如果修饰基本数据类型则是安全的。修饰的对象释放后,指针不会自动被置空,此时向对象发消息会崩溃。
相似
都可以修饰对象类型,但是assign修饰对象会存在问题。
总结
assign 适用于基本数据类型如int,float,struct等值类型,不适用于引用类型。因为值类型会被放入栈中,遵循先进后出原则,由系统负责管理栈内存。而引用类型会被放入堆中,需要我们自己手动管理内存或通过ARC管理。
weak 适用于delegate和block等引用类型,不会导致野指针问题,也不会循环引用,比较安全。
4、weak属性需要在dealloc中置nil么?
在ARC中,无论是strong修饰的对象还是weak修饰的对象,都不再需要在dealloc中将对象置为nil,编译器会自动帮我们处理,即使编译器不帮助我们处理,在属性所指的对象遭到摧毁时,属性值也会清空(nil out)。
5、ARC下,不显式指定任何属性关键字时,默认的关键字都有哪些?
- 原子性 – atomic
- 读写权限 – readwrite
- 内存管理 – 基础数据类型(assign),对象(strong)
联系方式
邮箱: xiebangyao_1994@163.com
相关账号:
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!