iOS开发多线程篇—线程安全
一、多线程的安全隐患
资源共享
1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源
比如多个线程访问同一个对象、同一个变量、同一个文件
当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题
示例一:
示例二:
问题代码:
1 //2 // YYViewController.m3 // 05-线程安全4 //5 // Created by apple on 14-6-23.6 // Copyright (c) 2014年 itcase. All rights reserved.7 //8 9 10 #import "YYViewController.h" 11 12 @interface YYViewController () 13 //剩余票数 14 15 @property(nonatomic,assign) int leftTicketsCount; 16 @property(nonatomic,strong)NSThread *thread1; 17 @property(nonatomic,strong)NSThread *thread2; 18 @property(nonatomic,strong)NSThread *thread3; 19 20 21 @end 22 23 24 @implementation YYViewController 25 26 27 - (void)viewDidLoad 28 { 29 [super viewDidLoad]; 30 31 //默认有20张票 32 33 self.leftTicketsCount=10; 34 35 //开启多个线程,模拟售票员售票 36 37 self.thread1=[[NSThread alloc]initWithTarget:self selector:@selector(sellTickets) object:nil]; 38 39 self.thread1.name=@"售票员A"; 40 41 self.thread2=[[NSThread alloc]initWithTarget:self selector:@selector(sellTickets) object:nil]; 42 43 self.thread2.name=@"售票员B"; 44 45 self.thread3=[[NSThread alloc]initWithTarget:self selector:@selector(sellTickets) object:nil]; 46 self.thread3.name=@"售票员C"; 47 } 48 49 50 -(void)sellTickets 51 { 52 while (1) { 53 //1.先检查票数 54 int count=self.leftTicketsCount; 55 if (count>0) { 56 //暂停一段时间 57 [NSThread sleepForTimeInterval:0.002]; 58 59 //2.票数-1 60 self.leftTicketsCount= count-1; 61 62 //获取当前线程 63 NSThread *current=[NSThread currentThread]; 64 NSLog(@"%@--卖了一张票,还剩余%d张票",current,self.leftTicketsCount); 65 }else 66 { 67 //退出线程 68 [NSThread exit]; 69 } 70 } 71 } 72 73 74 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 75 { 76 //开启线程 77 78 [self.thread1 start]; 79 [self.thread2 start]; 80 [self.thread3 start]; 81 82 } 83 84 @end
打印结果:
二、安全隐患分析
三、如何解决
互斥锁使用格式
@synchronized(锁对象) { // 需要锁定的代码 }
注意:锁定1份代码只用1把锁,用多把锁是无效的
代码示例:
1 //2 // YYViewController.m3 // 05-线程安全4 //5 // Created by apple on 14-6-23.6 // Copyright (c) 2014年 itcase. All rights reserved.7 //8 9 #import "YYViewController.h" 10 11 @interface YYViewController () 12 13 //剩余票数 14 @property(nonatomic,assign) int leftTicketsCount; 15 @property(nonatomic,strong)NSThread *thread1; 16 @property(nonatomic,strong)NSThread *thread2; 17 @property(nonatomic,strong)NSThread *thread3; 18 @end 19 20 @implementation YYViewController 21 22 - (void)viewDidLoad 23 { 24 [super viewDidLoad]; 25 //默认有20张票 26 self.leftTicketsCount=10; 27 //开启多个线程,模拟售票员售票 28 29 self.thread1=[[NSThread alloc]initWithTarget:self selector:@selector(sellTickets) object:nil]; 30 31 self.thread1.name=@"售票员A"; 32 33 self.thread2=[[NSThread alloc]initWithTarget:self selector:@selector(sellTickets) object:nil]; 34 35 self.thread2.name=@"售票员B"; 36 37 self.thread3=[[NSThread alloc]initWithTarget:self selector:@selector(sellTickets) object:nil]; 38 39 self.thread3.name=@"售票员C"; 40 } 41 42 43 -(void)sellTickets 44 { 45 while (1) { 46 @synchronized(self){//只能加一把锁 47 //1.先检查票数 48 49 int count=self.leftTicketsCount; 50 if (count>0) { 51 //暂停一段时间 52 [NSThread sleepForTimeInterval:0.002]; 53 //2.票数-1 54 55 self.leftTicketsCount= count-1; 56 //获取当前线程 57 NSThread *current=[NSThread currentThread]; 58 NSLog(@"%@--卖了一张票,还剩余%d张票",current,self.leftTicketsCount); 59 60 }else 61 { 62 //退出线程 63 [NSThread exit]; 64 } 65 } 66 } 67 } 68 69 70 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 71 { 72 73 //开启线程 74 [self.thread1 start]; 75 [self.thread2 start]; 76 [self.thread3 start]; 77 } 78 79 @end
执行效果图
互斥锁的优缺点
优点:能有效防止因多线程抢夺资源造成的数据安全问题
缺点:需要消耗大量的CPU资源
互斥锁的使用前提:多条线程抢夺同一块资源
相关专业术语:线程同步,多条线程按顺序地执行任务
互斥锁,就是使用了线程同步技术
四:原子和非原子属性
OC在定义属性时有nonatomic和atomic两种选择
atomic:原子属性,为setter方法加锁(默认就是atomic)
nonatomic:非原子属性,不会为setter方法加锁
atomic加锁原理
1 @property (assign, atomic) int age; 2 3 - (void)setAge:(int)age 4 { 5 6 @synchronized(self) { 7 _age = age; 8 } 9 }
原子和非原子属性的选择
nonatomic和atomic对比
atomic:线程安全,需要消耗大量的资源
nonatomic:非线程安全,适合内存小的移动设备
iOS开发的建议
所有属性都声明为nonatomic
尽量避免多线程抢夺同一块资源
尽量将加锁、资源抢夺的业务逻辑交给服务器端处理,减小移动客户端的压力
转载于:https://www.cnblogs.com/LifeTechnologySupporter/p/10353096.html
iOS开发多线程篇—线程安全相关推荐
- iOS开发多线程篇—线程的状态
iOS开发多线程篇-线程的状态 一.简单介绍 线程的创建: self.thread=[[NSThread alloc]initWithTarget:self selector:@selector(te ...
- iOS开发多线程篇—多线程简介
iOS开发多线程篇-多线程简介 一.进程和线程 1.什么是进程 进程是指在系统中正在执行的一个应用程序 每一个进程之间是独立的.每一个进程均执行在其专用且受保护的内存空间内 比方同一时候打开QQ.Xc ...
- iOS开发多线程篇—自定义NSOperation
iOS开发多线程篇-自定义NSOperation 一.实现一个简单的tableView显示效果 实现效果展示: 代码示例(使用以前在主控制器中进行业务处理的方式) 1.新建一个项目,让控制器继承自UI ...
- iOS开发——高级篇——线程同步、线程依赖、线程组
前言 对于iOS开发中的网络请求模块,AFNet的使用应该是最熟悉不过了,但你是否把握了网络请求正确的完成时机?本篇文章涉及线程同步.线程依赖.线程组等专用名词的含义,若对上述名词认识模糊,可先进行查 ...
- iOS开发多线程篇—多线程简单介绍
一.进程和线程 1.什么是进程 进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 比如同时打开QQ.Xcode,系统就会分别启动2个进程 通过& ...
- iOS开发——多线程篇——GCD
一.基本概念 1.简介 什么是GCD 全称是Grand Central Dispatch,可译为"牛逼的中枢调度器" 纯C语言,提供了非常多强大的函数 GCD的优势 GCD是苹果公 ...
- ios开发多线程篇--异步加载网络图片GCD
一.异步加载网络图片 1.ATS (1)简介 从iOS9.0开始,如果按照以前的方式写代码,在访问网络的时候 ,会报以下警告信息: App Transport Security has blocked ...
- iOS开发网络篇—多线程断点下载
iOS开发网络篇-多线程断点下载 说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了同时开启多条线程下载一个较大的文件.因为实现过程较为复杂,所以下面贴出完整的代码. 实现思路:下载开始, ...
- iOS开发里的线程安全机制
[编者按]本文为再读苹果<Threading Programming Guide>笔记第四篇,主要分享了线程安全机制以及设计时所需要注意的事项.从最初的"什么是线程"到 ...
最新文章
- Ehcache的基本概念
- 宝塔安装php遇错libicui18n.so.42: cannot open shared object file: No such file or directory
- 云计算到底是谁发明的?
- 父子组建传值_浅谈Vue父子组件和非父子组件传值问题
- php取整函数ceil,floor,round,intval函数的区别
- QML笔记-对QML中信号与槽的进一步认识
- oracle有三种类型的异常错误: 预定义 ( Predefined )错误里面的常见错误
- Python操作SQLServer示例
- 手把手教你搭建FastDFS集群(上)
- DFA算法实现 敏感词过滤
- 易语言 精易模块 网页_访问 获取显示验证码图片
- 百度搜索下拉框,下拉菜单怎么做?如何刷?
- 街头霸王5显示正在登陆服务器无法进入游戏,街头霸王5打不开怎么办 无法进入游戏解决方法...
- Java类的继承学生研究生类图_UML part3 类图、对象图
- qt开发之获取鼠标的相对位置和绝对位置
- [蓝桥杯2022初赛] 砍竹子
- JRebel热部署,从此告别一遍一遍重启项目
- 在知识蒸馏中不要忘记教师网络detach()
- Cris 的Python笔记(六):函数基础
- 撤销和重做实现-第二部分(命令模式)