iOS核心笔记——多线程-原子/非原子属性

1、原子属性:

1-1、nonatomic与atomic:
  • nonatomic : 非原子属性;
  • atomic : 原子属性;
    • 线程安全的,针对多线程设计的属性修饰符,是默认值.
    • 保证同一时间只有一个线程能够写入,但是同一个时间多个线程都可以读取;
    • 单写多读 : 单个线程写入write,多个线程可以读取read
    • atomic 本身就有一把锁,自旋锁

1-2、nonatomicatomic对比:
  • nonatomic : 非线程安全,适合内存小的移动设备;
  • atomic : 线程安全,需要消耗大量的资源.性能比非原子属性要差。

1-3、iOS开发的建议:
  • 所有属性都声明为nonatomic,性能更高;
  • 尽量避免多线程抢夺同一块资源;
  • 尽量将加锁、资源抢夺的业务逻辑交给服务器端处理,减小移动客户端的压力。

2、模拟原子属性:

2-1、定义属性:
1./// 非原子属性[email protected] (nonatomic,strong) NSObject *obj1;3./// 原子属性:内部有"自旋锁"[email protected] (atomic,strong) NSObject *obj2;5./// 模拟原子属性[email protected] (atomic,strong) NSObject *obj3;

?了解: 重写非原子属性的settergetter方法:

?了解: 1、重写了原子属性的setter方法之后,会覆盖原子属性内部的自旋锁,使其失效;然后我们加入互斥锁,来模拟单写多读

?了解: 2、重写了属性的settergetter方法之后,系统就不会再帮我们生成待下划线的成员变量;使用合成指令@synthesize,就可以手动的生成带下划线的成员变量。



示例程序:

1.// 合成指令[email protected] obj3 = _obj3;3.4./// obj3的setter方法5.- (void)setObj3:(NSObject *)obj36.{7.    @synchronized(self) {8.        _obj3 = obj3;9.    }10.}11.12./// obj3的getter方法13.- (NSObject *)obj314.{15.    return _obj3;16.}

2-2、性能测试:
1./// 测试"非原子属性","互斥锁","自旋锁"的性能2.- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event3.{4.    NSInteger largeNum = 1000*1000;5.6.    NSLog(@"非原子属性");7.    CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();8.    for (int i = 0; i < largeNum; i++) {9.        self.obj1 = [[NSObject alloc] init];10.    }11.    NSLog(@"非原子属性 => %f",CFAbsoluteTimeGetCurrent()-start);12.13.    NSLog(@"原子属性");14.    start = CFAbsoluteTimeGetCurrent();15.    for (int i = 0; i < largeNum; i++) {16.        self.obj2 = [[NSObject alloc] init];17.    }18.    NSLog(@"原子属性 => %f",CFAbsoluteTimeGetCurrent()-start);19.20.    NSLog(@"模拟原子属性");21.    start = CFAbsoluteTimeGetCurrent();22.    for (int i = 0; i < largeNum; i++) {23.        self.obj3 = [[NSObject alloc] init];24.    }25.    NSLog(@"模拟原子属性 => %f",CFAbsoluteTimeGetCurrent()-start);26.}

3、互斥锁和自旋锁对比:

3-1、共同点:
  • 都能够保证同一时间,只有一条线程执行锁定范围的代码
3-2、不同点:
  • 互斥锁:如果发现有其他线程正在执行锁定的代码,线程会进入休眠状态,等待其他线程执行完毕,打开锁之后,线程会重新进入就绪状态;等待被CPU重新调度。
  • 自旋锁:如果发现有其他线程正在执行锁定的代码,线程会以死循环的方式;一直等待锁定代码执行完成。

4、开发建议:

    1. 所有属性都声明为nonatomic,原子属性和非原子属性的性能几乎一样。
    2. 尽量避免多线程抢夺同一块资源。
    3. 要实现线程安全,必须要用到;无论什么锁,都是有性能消耗的。
    4. 自旋锁更适合执行非常短的代码,死循环内部不适合写复杂的代码。
    5. 尽量将加锁,资源抢夺的业务逻辑交给服务器端处理,减小移动客户端的压力。
    6. 为了流畅的用户体验,UIKit类库的线程都是不安全的;所以我们需要在主线程(UI线程)上更新UI。
    7. 所有包含NSMutable的类都是线程不安全的,在做多线程开发的时候,需要注意多线程同时操作可变对象的线程安全问题。

时间: 2024-10-17 15:17:33

iOS核心笔记——多线程-原子/非原子属性的相关文章

iOS核心笔记——多线程-GCD

1.GCD简介: ?了解:GCD全称为"Grand Central Dispatch",纯C语言,GCD提供了非常多功能强大的函数:GCD中所有的函数都包含于Libdispatch库中. 1-1.使用GCD的优势: ?了解:1.GCD是苹果公司为多核的并行运算提出的解决方案: ?了解:2.GCD会自动利用更多的CPU内核(例如:双核.四核): ?了解:3.GCD会自动管理线程的生命周期(创建线程.调度任务.销毁线程). 1-2.GCD两大核心概念: 名称 作用: 任务 执行什么操作 队

iOS核心笔记——多线程-基本知识

1.基本概念: 1-1.进程: 定义:进程是指系统中正在运行的应用程序. 了解:每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间里. 1-2.线程: 一个进程要想执行任务,必须要有一条线程(即:每一个进程至少拥有一条线程,这条线程便是主线程). 一个进程中的所有任务都是在线程中执行. 线程是进程的基本执行单元. 1-3.线程的串行: 线程中所有的任务都是串行执行的,即:如果要在1个线程中执行多个任务时,多个任务只能按顺序执行:且同一时刻,1个线程只能执行1个任务. 1-4.进程与线

iOS核心笔记——多线程-单例设计模式

1.单例设计模式: 2.单例设计模式实现(ARC模式): 2-1.单例设计模式步骤: ?重要:①提供一个静态全局变量:②重写allocWithZone方法,使用一次性方法保证只分配一次存储空间.③提供快速创建单例对象的类方法:④严谨起见,还应重写copyWithZone.mutableCopyWithZone方法. 2-2.确保内存分配: 2-3.提供类方法: 3.单例模式三个问题: ?重要:①:怎么实现一个单例模式?(重写allocWithZone方法)②:内部是怎么确保只分配一次内存?(在a

iOS核心笔记——UICollectionView-布局对象

iOS核心笔记--UICollectionView-布局对象 1.UICollectionView布局对象: 1-1.UICollectionViewLayout: ?了解:1.UICollectionViewLayout没有itemSize属性,而collectionView的cell的大小不能为0或者小于0:所以,通常collectionView使用其子类UICollectionViewFlowLayout布局cell. ?了解:2.UICollectionViewLayout中声明了布局可

iOS核心笔记——UICollectionView-辅助视图

iOS核心笔记--UICollectionView-辅助视图 1.UICollectionView辅助视图: ?了解:UICollectionView中的头部视图.尾部视图都是使用注册机制 + 重用机制,提高程序的执行效率,其头尾部视图类型均为:UICollectionReusableView.注册辅助视图时使用字符串区分注册的视图为头部还是尾部视图,其区分字符串为:UICollectionElementKindSectionHeader(头部视图).UICollectionElementKin

IOS学习笔记 -- 多线程

多线程1.多线程的原理 1>.同一时间,CPU只能处理1条线程,只有1条线程在工作(执行) 2>.多线程并发(同时)执行,其实是CPU快速地在多条线程之间调度(切换) 3>.如果CPU调度线程的时间足够快,就造成了多线程并发执行的假象如果线程非常非常多,会发生: 1>.CPU会在N多线程之间调度,CPU会累死,消耗大量的CPU资源 2>.每条线程被调度执行的频次会降低(线程的执行效率降低) 2.多线程的优缺点 1>.多线程的优点 能适当提高程序的执行效率 能适当提高资源

iOS核心笔记——富文本属性

1.NSFontAttributeName : 字体 NSString *const NSFontAttributeName;(字体) 该属性所对应的值是一个 UIFont 对象.该属性用于改变一段文本的字体.如果不指定该属性,则默认为12-point Helvetica(Neue). 2.NSParagraphStyleAttributeName : 段落 NSString *const NSParagraphStyleAttributeName;(段落) 该属性所对应的值是一个 NSPara

iOS核心笔记——RunLoop-基础

1.RunLoop介绍: ?了解:RunLoop从字面意思看就是运行循环.跑圈,通常情况下,一个线程一次只能执行一个任务:任务执行完毕后线程就会进入消亡状态随之退出.有时候我们希望线程执行完任务之后还能随时处理事件且不退出,所以,iOS提供了RunLoop. 1-1.什么是RunLoop? ?重要:RunLoop实际上就是一个对象,RunLoop对象管理其需要处理的事件和消息:RunLoop能够让线程在没有处理消息时进入休眠状态以避免占用资源.在监听到事件源发送的消息时立刻唤醒线程.RunLoo

iOS核心笔记——网络编程-HTTPS协议

1.HTTPS的基本使用: 1.HTTPS简单说明: ?了解:HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版. ?重要:即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL. 它是一个URI scheme(抽象标识符体系),句法类同http:体系.用于安全的HTTP数据传输. ?重要:https:URL:表明它使用了HTTPS,