iOS开发多线程篇—线程安全

简介: iOS开发多线程篇—线程安全   一、多线程的安全隐患 资源共享 1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源 比如多个线程访问同一个对象、同一个变量、同一个文件 当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题 示例一: 示例二: 问题代码: 1 // 2 // YYViewController.

iOS开发多线程篇—线程安全

 

一、多线程的安全隐患

资源共享

1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源

比如多个线程访问同一个对象、同一个变量、同一个文件

当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题

示例一:

示例二:

问题代码:

 1 //
 2 //  YYViewController.m
 3 //  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.m
 3 //  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在定义属性时有nonatomicatomic两种选择

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 }

 

原子和非原子属性的选择

nonatomicatomic对比

atomic线程安全,需要消耗大量的资源

nonatomic非线程安全,适合内存小的移动设备

 

iOS开发的建议

所有属性都声明为nonatomic

尽量避免多线程抢夺同一块资源

尽量将加锁、资源抢夺的业务逻辑交给服务器端处理,减小移动客户端的压力

目录
相关文章
|
4天前
|
JavaScript 搜索推荐 Android开发
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
23 8
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
|
5天前
|
Python
python3多线程中使用线程睡眠
本文详细介绍了Python3多线程编程中使用线程睡眠的基本方法和应用场景。通过 `time.sleep()`函数,可以使线程暂停执行一段指定的时间,从而控制线程的执行节奏。通过实际示例演示了如何在多线程中使用线程睡眠来实现计数器和下载器功能。希望本文能帮助您更好地理解和应用Python多线程编程,提高程序的并发能力和执行效率。
34 20
|
11天前
|
安全 Java C#
Unity多线程使用(线程池)
在C#中使用线程池需引用`System.Threading`。创建单个线程时,务必在Unity程序停止前关闭线程(如使用`Thread.Abort()`),否则可能导致崩溃。示例代码展示了如何创建和管理线程,确保在线程中执行任务并在主线程中处理结果。完整代码包括线程池队列、主线程检查及线程安全的操作队列管理,确保多线程操作的稳定性和安全性。
|
1月前
|
iOS开发 开发者
uniapp开发ios打包Error code = -5000 Error message: Error: certificate file(p12) import failed!报错问题如何解决
uniapp开发ios打包Error code = -5000 Error message: Error: certificate file(p12) import failed!报错问题如何解决
143 67
uniapp开发ios打包Error code = -5000 Error message: Error: certificate file(p12) import failed!报错问题如何解决
|
2月前
|
存储 监控 API
app开发之安卓Android+苹果ios打包所有权限对应解释列表【长期更新】-以及默认打包自动添加权限列表和简化后的基本打包权限列表以uniapp为例-优雅草央千澈
app开发之安卓Android+苹果ios打包所有权限对应解释列表【长期更新】-以及默认打包自动添加权限列表和简化后的基本打包权限列表以uniapp为例-优雅草央千澈
90 11
|
2月前
|
NoSQL Redis
单线程传奇Redis,为何引入多线程?
Redis 4.0 引入多线程支持,主要用于后台对象删除、处理阻塞命令和网络 I/O 等操作,以提高并发性和性能。尽管如此,Redis 仍保留单线程执行模型处理客户端请求,确保高效性和简单性。多线程仅用于优化后台任务,如异步删除过期对象和分担读写操作,从而提升整体性能。
79 1
|
2月前
|
iOS开发 开发者 MacOS
深入探索iOS开发中的SwiftUI框架
【10月更文挑战第21天】 本文将带领读者深入了解Apple最新推出的SwiftUI框架,这一革命性的用户界面构建工具为iOS开发者提供了一种声明式、高效且直观的方式来创建复杂的用户界面。通过分析SwiftUI的核心概念、主要特性以及在实际项目中的应用示例,我们将展示如何利用SwiftUI简化UI代码,提高开发效率,并保持应用程序的高性能和响应性。无论你是iOS开发的新手还是有经验的开发者,本文都将为你提供宝贵的见解和实用的指导。
145 66
|
2月前
|
开发框架 Android开发 iOS开发
安卓与iOS开发中的跨平台策略:一次编码,多平台部署
在移动应用开发的广阔天地中,安卓和iOS两大阵营各占一方。随着技术的发展,跨平台开发框架应运而生,它们承诺着“一次编码,到处运行”的便捷。本文将深入探讨跨平台开发的现状、挑战以及未来趋势,同时通过代码示例揭示跨平台工具的实际运用。
173 3
|
2月前
|
Java 调度 Android开发
安卓与iOS开发中的线程管理差异解析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自拥有独特的魅力。如同东西方文化的差异,它们在处理多线程任务时也展现出不同的哲学。本文将带你穿梭于这两个平台之间,比较它们在线程管理上的核心理念、实现方式及性能考量,助你成为跨平台的编程高手。
|
3月前
|
存储 前端开发 Swift
探索iOS开发:从新手到专家的旅程
本文将带您领略iOS开发的奇妙之旅,从基础概念的理解到高级技巧的掌握,逐步深入iOS的世界。文章不仅分享技术知识,还鼓励读者在编程之路上保持好奇心和创新精神,实现个人成长与技术突破。

热门文章

最新文章