文档章节

iOS-多线程与锁

麦兜卖鱼丸
 麦兜卖鱼丸
发布于 2017/04/28 09:52
字数 881
阅读 8
收藏 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上MDM技术相关资料整理及汇总

一、MDM相关知识: MDM (Mobile Device Management ),即移动设备管理。在21世纪的今天,数据是企业宝贵的资产,安全问题更是重中之重,在移动互联网时代,员工个人的设备接入企业网络并查...

移动互联百科
2013/10/06
0
0
IOS12开发者预览版第二版使用评测

     手头有一部iPhone 6s Plus,因为之前看同学和朋友们升到IOS 11后手机变得非常卡顿所以没有升级。最近偶然看到IOS 12针对旧机型做了性能优化,号称提升70%相机打开速度、50%键盘显示...

张旭乾
06/23
0
0
如何判断你是合格的高级iOS开发工程师?

前言 随着移动互联网的高速发展泄洪而来,有意学习移动开发的人越来越多了,竞争也是越来越大,需要学习的东西很多。如何才能在激烈的移动开发者竞争中一枝独秀,成为一名真正合格的高级iOS...

_小迷糊
05/26
0
0
(转)直接拿来用!最火的iOS开源项目(二)

“每一次的改变总意味着新的开始。”这句话用在iOS上可谓是再合适不过的了。GitHub上的iOS开源项目数不胜数,iOS每一次的改变,总会引发iOS开源项目的演变,从iOS 1.x到如今的iOS 7,有的项目...

孙启超
2013/06/21
0
1
[help] ios 锁屏下音频的播放&暂停问题

用ios(safari)访问自己的网站(非app)后点击音频播放,然后锁屏,再亮屏的时候便是如上图所示 有以下不解: 点击中间暂停按钮可暂停,但是再次点击却是从头播放,多次反复点击后音频信息消失(进度条...

顾慎为
06/27
0
0

没有更多内容

加载失败,请刷新页面

加载更多

如何通过 J2Cache 实现分布式 session 存储

做 Java Web 开发的人多数都会需要使用到 session (会话),我们使用 session 来保存一些需要在两个不同的请求之间共享数据。一般 Java 的 Web 容器像 Tomcat、Resin、Jetty 等等,它们会在...

红薯
今天
1
0
C++ std::thread

C++11提供了std::thread类来表示一个多线程对象。 1,首先介绍一下std::this_thread命名空间: (1)std::this_thread::get_id():返回当前线程id (2)std::this_thread::yield():用户接口...

yepanl
今天
2
0
Nignx缓存文件与动态文件自动均衡的配置

下面这段nginx的配置脚本的作用是,自动判断是否存在缓存文件,如果有优先输出缓存文件,不经过php,如果没有,则回到php去处理,同时生成缓存文件。 PHP框架是ThinkPHP,最后一个rewrite有关...

swingcoder
今天
1
0
20180920 usermod命令与用户密码管理

命令 usermod usermod 命令的选项和 useradd 差不多。 一个用户可以属于多个组,但是gid只有一个;除了gid,其他的组(groups)叫做扩展组。 usermod -u 1010 username # 更改用户idusermod ...

野雪球
今天
1
0
Java网络编程基础

1. 简单了解网络通信协议TCP/IP网络模型相关名词 应用层(HTTP,FTP,DNS等) 传输层(TCP,UDP) 网络层(IP,ICMP等) 链路层(驱动程序,接口等) 链路层:用于定义物理传输通道,通常是对...

江左煤郎
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部