文档章节

iOS-多线程与锁

麦兜卖鱼丸
 麦兜卖鱼丸
发布于 2017/04/28 09:52
字数 881
阅读 13
收藏 0

前言

项目中使用多线程,首要考虑的问题就是线程安全问题,普遍存在的是多个线程同时访问同一内存(存在读写操作,单独的读操作是不会发生冲突的)发生的数据冲突或者是crash。往往我们的解决方案一般采用同步队列或者是加锁,但是要考虑死锁问题。

下面解释几个名词;

(1)队列类型

同步队列:一个一个按照FIFO的执行任务,后一个任务需要等待前一个任务执行完成后才能被执行;

并发队列:后一个任务不需要等待前一个任务执行完成就可以被执行,若是异步提交任务到异步队列则可以并发执行多个任务,若是同步提交任务则是一个一个执行任务。

(2)执行方式

同步方式会阻塞当前线程,异步方式不会阻塞当前线程(立即返回)。

(3)加锁

对于锁的解释网络上有很多文章,看下面几篇文章

深入理解 iOS 开发中的锁

【iOS】从同步锁到多线程

非递归锁,如NSLock等;

递归锁:同一个线程可以多次加锁而不会造成死锁,但会阻塞其他线程访问(lock与unlock成对出现)。官方文档对递归锁NSRecursiveLock的解释;

A recursive lock is a variant on the mutex lock. A recursive lock allows a single thread to acquire the lock multiple times before releasing it. Other threads remain blocked until the owner of the lock releases the lock the same number of times it acquired it. Recursive locks are used during recursive iterations primarily but may also be used in cases where multiple methods each need to acquire the lock separately.

 

容易出现死锁的情况;

(1)使用队列造成的死锁,同一线程多次同步提交任务到同步队列,同步执行方式会阻塞当前线程,而同步队列想要执行后一个任务必须要等到前一个任务完成后,后一个任务才会被执行,造成前后任务相互等待线程休眠,最后导致死锁。比较经典的死锁的例子;

dispatch_sync(dispatch_get_main_queue(), ^{
        
        NSLog(@"任务二");
    });
    
    NSLog(@"任务一");

由于同步执行方式阻塞当前线程,任务一等待任务二执行完才能够执行,但是由于任务二被添加到任务一之后,所以任务二需等待任务一执行完才能被执行,于是造成了死锁。

 

(2)使用加锁造成的死锁,使用非递归锁在没有被解锁的情况下多次加锁则会造成加锁死锁,原因是未解锁多次加锁会出现前一次加锁想无法解锁,后一次加锁获取不到锁对象的情况,像队列一样,会造成相互等待线程休眠的情况,从而导致死锁。看一个例子;

NSLock *theLock = [[NSLock alloc] init];
//NSRecursiveLock *theLock = [[NSRecursiveLock alloc] init];
 
void MyRecursiveFunction(int value)
{
    [theLock lock];
    if (value != 0)
    {
        --value;
        MyRecursiveFunction(value);
    }
    [theLock unlock];
}
 
MyRecursiveFunction(5);

上述代码是在递归调用中使用非递归锁加锁,会造成加锁死锁,改成递归锁后正常执行。

 

总结

使用多线程不仅要考虑线程安全,还需要考虑死锁的情况,今天只是分析以下两种导致死锁的情况;

(1)同步提交任务至同步队列;

(2)在有递归或者是循环情况下,使用非递归锁加锁。

© 著作权归作者所有

共有 人打赏支持
下一篇: 解决方案研究
麦兜卖鱼丸
粉丝 12
博文 69
码字总数 69333
作品 0
桂林
iOS工程师
私信 提问
iOS多种刷新样式、音乐播放器、仿抖音视频、旅游App等源码

iOS精选源码 企业级开源项目,模仿艺龙旅行App(http://www.code4app.com/thread-14774-1-1.html) 3D立体相册,可以旋转的立方体(http://www.code4app.com/thread-14966-1-1.html) 横竖屏切换...

Android爱开源
10/17
0
0
iOS 7.1.2 即将发布 修复多项漏洞

据外媒报道,苹果已向部分运营商提供了iOS 7.1.2的一个版本,版本号为11D257,并要求他们在6月27日(下周五)对该版本签字认可。这意味着iOS 7.1.2很可能在随后一周公开发布。 据称,此次更新...

oschina
2014/06/22
1K
4
苹果发布 iOS 9.3.3 正式版和 iOS 10 beta 3 测试版

苹果今天发布了 iOS 9.3.3 正式版,iOS 9.3.3 从5月23日开始测试,一共有5个测试版。对于 iOS 9 用户来说,可以通过 OTA 或者 iTunes 完成升级。iOS 9.3.3 主要改进系统底层性能,并修复 Bu...

oschina
2016/07/19
2.7K
6
iOS 10 发布:10 大新功能、预装 App 可删、信息更好玩

苹果在今天举行的 WWDC 发布会上,正式推出了 iOS 10。iOS 10 拥有10大新功能,系统的各个方面都得到了增强,信息应用功能更强大,更好玩。照片应用支持全新回忆功能,可以自动整理照片。Sir...

oschina
2016/06/14
4.2K
29
苹果公司发布 iOS 8 重新定义通知中心

6月3日消息,一年一度的苹果开发者大会于北京时间6月3日凌晨1点在美国旧金山开幕。苹果公司在会上发布了最新的移动设备操作系统iOS 8。 据介绍,在全新的iOS 8中,苹果重新定义了通知中心,可...

oschina
2014/06/03
1K
4

没有更多内容

加载失败,请刷新页面

加载更多

[LintCode] Serialize and Deserialize Binary Tree(二叉树的序列化和反序列化)

描述 设计一个算法,并编写代码来序列化和反序列化二叉树。将树写入一个文件被称为“序列化”,读取文件后重建同样的二叉树被称为“反序列化”。 如何反序列化或序列化二叉树是没有限制的,你...

honeymose
15分钟前
0
0
java框架学习日志-7(静态代理和JDK代理)

静态代理 我们平时去餐厅吃饭,不是直接告诉厨师做什么菜的,而是先告诉服务员点什么菜,然后由服务员传到给厨师,相当于服务员是厨师的代理,我们通过代理让厨师炒菜,这就是代理模式。代理...

白话
今天
22
0
Flink Window

1.Flink窗口 Window Assigner分配器。 窗口可以是时间驱动的(Time Window,例如:每30秒钟),也可以是数据驱动的(Count Window,例如:每一百个元素)。 一种经典的窗口分类可以分成: 翻...

满小茂
今天
17
0
my.ini

1

architect刘源源
今天
15
0
docker dns

There is a opensource application that solves this issue, it's called DNS Proxy Server It's a DNS server that solves containers hostnames, if could not found a hostname that mat......

kut
今天
15
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部