Swift线程安全详解-概念,三种锁,死锁,Atomic,synchronized

原创Blog,转载请注明出处
http://blog.csdn.net/hello_hwc?viewmode=list
我的stackoverflow

profile for Leo on Stack Exchange, a network of free, community-driven Q&A sites


前言:最近app中的日历小概率的在currentCalendar这个方法崩溃,看了下call
tree。研究了下,是线程安全问题。这里,就系统性的总结下线程安全这部分。

之后的博客绝大部分源码会用Swift来写了。


一些资料

  1. objc.io上对应多线程这一章
  2. Apple thread safe

iOS中的线程

什么是线程?
线程是操作系统进行调度的最小单位,它被包含在进程中,是进程运作的实际单位。在单核系统中,按照时间片轮转的方式实现线程的并发执行,在多核系统中,能够真正实现线程同时执行。

iOS中与多线程相关的常用的有NSThread,GCD,NSOperationQueue.还有一个不常用,但是理解很重要的NSRunloop。


什么是线程安全?

当一段代码被多个线程执行,执行后的结果和多个线程依次执行后的结果一致,那么这段代码就是线程安全的。

再看看WIKI中的定义

A piece of code is thread-safe if it only manipulates shared data structures in a manner that guarantees safe execution by multiple threads at the same time.
一段代码在多个线程上调用,并且共享一段内存空间。如果代码能够安全执行,就是线程安全的。


举个例子

NSMutableArray不是线程安全的,那么以下代码就会小概率崩溃

        let queue1 = dispatch_queue_create("com.test.queue1", DISPATCH_QUEUE_SERIAL)
        let queue2 = dispatch_queue_create("com.test.queue1", DISPATCH_QUEUE_SERIAL)
        dispatch_async(queue1) { () -> Void in
            for index in 1...500{
                self.emptyArray.addObject(NSNumber(integer: index))
            }
        }
        dispatch_async(queue2) { () -> Void in
            for index in 500...1000{
                self.emptyArray.addObject(NSNumber(integer: index))
            }
        }

运行的话,崩溃如图
这里写图片描述

错误Log

malloc: * error for object 0x7fb5804a9d40: pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug

注意,这种崩溃是小概率的,但是当用户量大的时候,就会知道小概率也是不可忽视的
这不会详细介绍NSMutableArray的背后实现原理,感兴趣的同学可以看看这篇文章

错误原因-抽象到malloc和free的问题

每次malloc会分配新的地址,然后free释放。有可能按照如图的方式malloc-malloc-free-free.这样同一个地址会free两次,也就crash了。类似的在ARC中release一个reference count为0的对象也会出错。


UIKit以及Fundation

事实上,大多数Cocoa提供的Api都不是线程安全的,尤其是与UI相关的UIKit,只能在主线程上操作。

在后台更新UI是很多开发者容易犯的错误

那么,为什么不把Cocoa的API写成线程安全的呢?Apple那么多天才工程师,难道解决不了吗?

答案很明显:为了执行效率,大多数的时候不需要并行的执行一段代码,而加上锁,递归锁之类的东西,执行效率会降低很多。需要线程安全的时候,开发者自己维护就可以了。

通常,不可变对象是线程安全的,可变对象不是线程安全的
以下Fundation对象是线程安全的,

意味着,你可以在多个线程中访问一个对象(读写),而不需要加锁

NSArray
NSAssertionHandler
NSAttributedString
NSCalendarDate
NSCharacterSet
NSConditionLock
NSConnection
NSData
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值