atomic 和noatomic

来源:互联网 发布:拍a发b淘宝会被降权吗 编辑:程序博客网 时间:2024/04/30 09:57

曾经面试时候被被问到最多的问题是 nonatomic是啥意思, 当时对这个东西理解有限,只是知道原子操作和非原子操作的区别。

OK, 其实这个东西是和多线程有关系的。

你在什么时候会用到多线程?理论我们都懂,但是用的好不好就看理解深不深了,大多时候我们会在download的时候用到这个东西,但是远远不是如此,用多线程还是为了提高性能和用户体验,对于iOS来说主线程用来刷新UI,所以如果我们要做一件耗时长的事情,同时不希望用户UI被block,我们几乎没有选择就是使用子线程(多线程)了,但是,这种情况其实不多。因为很耗时间的事情在iOS这种移动设备上最常见的就是webservice call,因为网络的问题我们需要等待,但是在这个级别上早就有各种优秀的算法和框架进行了优化,最常见的就是异步访问。

很早时候就知道多线程和异步,那个时候很不明白线程阻塞和同步到底有什么区别,现在明白了,区别就是多线程和单线程...阻塞说的是多个线程争抢一个资源,为了保证写数据不出乱子,只好让一个线程独占该数据,其他线程排队等着它,这个状态叫阻塞,而同步是跳出线程概念的一种机制,本质上说同步和异步可能也是通过使用多线程完成的,但是两者没有任何必然联系,甚至从逻辑上完全独立的,框架为我们实现了同步方法,那么这个方法在我们调用时没有返回结果前是绝对不会继续往下执行的,而异步方法就是说不让程序等着结果(其实也就是不阻塞当前线程,注意这里的阻塞的原因和行为与线程同步的阻塞完全不同,这里的阻塞是阻塞了当前执行的线程,而不是让其他线程阻塞等着自己)

我们经常使用异步用于webservice call,为的是在进行某个网络请求,比如刷新文章内容的时候让用户可以去干别的,比如说,刷新当前这个文章,同时让他可以浏览文章的评论或者提交自己的什么其他请求,因为异步是框架实现,所以当call back时,我们才继续处理刚才请求的那些东西。

那么什么时候用多线程呢?先说一个以前做的例子,不知什么原因以前实现了一个异步web调用,但是把它放到了一个子线程里面,发生了什么事情??没有call back,为啥呢异步这种机制啊是管杀不管埋的,它自己发起请求,只能在主线程中等着回调,子线程的话(NSThread)根本不知道有这回事,codes执行完,线程就结束了,call back当然回不来了,当时做了个处理把线程又放了个阻塞,等着它...尴尬

后来用上了iOS的NSOperation 和更底层的dispatch_asyc...原来框架对于这种在子线程中发起的请求也是有它自己的支持的...

从逻辑上看,其实完全不能理解为什么要把web请求放到子线程去,但从实际情况看,如果同时发起了太多的web请求主线程也会发生明显的卡死,可见异步调用这种东西对于主线程还是有些影响的,也许它用了那些资源,也许用了CPU时间片...也许...不知道,没深研究过...

所以看来还是会用到子线程的,那么问题就来了,因为同时发起一大堆线程并请求了web call,后面就会有一大堆层次不齐的回调,难免不同回调去改了同一个类的同一个变量,这时候atomic就发挥作用了,如果一个回调set了atomic的变量,那么其他同样操作就要等着,排队来...但是有个问题为什么么我的多个请求要刷新同一个东西?所以这就是设计要考虑的,比如我希望加一个评论,那么在评论页需要刷新,评论列表也需要刷新,可是对于iOS这种小屏幕,我是有多需要让评论页面和评论列表放在同一个屏幕上呢?真正需要3,4个线程同时操作一个数据的情况简直太少太少了,如果真有先要考虑设计是不是不合理...

但是你去查文档会发现,推荐优先声明成nonatomic变量,因为atomic可能会影响性能,所以还是那句话,线程多了性能也还是有很大影响的...所以做程序架构的原则上就是,尽量减少多线程的可能,比如上面说的例子,为什么要同时发起多个请求呢?想干什么呢?除了下载,其实一般都不需要同时做大量的请求,比如要加载满屏的图片,肯定需要同时加载个几十个的,那么可能不得不多线程处理,但是还需要考虑尽量减少线程数目,比如40个分5个线程,每个线程负责8个,因为对于用户来说你先加载每行第一个给他看,和完全按顺序加载区别不是太大,但是对程序性能就有影响,所以,在这个前提下再想我这个变量要不要atomatic,最后要注意不写属性默认是atomatic的,所以最好都写上,毕竟程序员应该更多的自己控制自己写出来的东西。

追加一句这玩意是给自动setter getter用的...自己实现的话貌似...还没研究过...

0 0