ios开发之多线程资源争夺
上一篇介绍了常用的多线程技术,目前开发中比较常用的是GCD,其它的熟悉即可。多线程是为了同步完成多项任务,不是为了提高运行效率,而是为了提高资源使用率来提高系统的整体性能,但是会出现多个线程对同一资源的抢夺,可能会引起线程的安全问题。 这时候可能需要创建一个单例对象来解决资源争夺问题,比较典型的是“卖票”问题
1、单例对象的创建
1> 定义一个全局的静态变量,记录第一次被实例化出来的对象,并在后续使用
2> 重写allocWithZone方法,并利用dispatch_once_t实例化线程安全的对象
3> 定义以shared或者default开头的类方法,供外界创建
1 #import <Foundation/Foundation.h> 2 3 @interface Tickets : NSObject 4 5 // 要使用互斥锁,需要两个条件 6 // 1. 将要强夺的资源设置为原子属性,只有设置了原子属性,才能够保证线程安全 7 // 2. 在读写原子属性的代码处,使用互斥锁@synchronized 8 @property (atomic, assign) NSInteger num; // 票数 9 10 // 提供给外界的类方法,一般以shared或者default开头 11 + (instancetype)sharedTickets; 12 13 @end
1 #import "Tickets.h" 2 3 static Tickets *_instance; 4 5 @implementation Tickets 6 7 + (id)allocWithZone:(struct _NSZone *)zone 8 { 9 // dispatch_once_t是gcd提供的一种多线程实例化对象的方法 10 // 使用此方法,可以保证在多线程情况下,始终仅能实例化出来一个对象 11 static dispatch_once_t onceToken; 12 dispatch_once(&onceToken, ^{ 13 _instance = [super allocWithZone:zone]; 14 }); 15 16 return _instance; 17 } 18 19 + (instancetype)sharedTickets 20 { 21 if (!_instance) { 22 _instance = [[Tickets alloc] init]; 23 } 24 25 return _instance; 26 } 27 28 @end
2、 创建多个异步线程,并执行卖票方法
1 - (void)viewDidLoad 2 { 3 [super viewDidLoad]; 4 5 [Tickets sharedTickets].num = 30; 6 7 // 创建多个线程异步售票 8 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 9 10 dispatch_async(queue, ^{ 11 [self sellTicketBy:@"p-1"]; 12 }); 13 14 dispatch_async(queue, ^{ 15 [self sellTicketBy:@"p-2"]; 16 }); 17 18 }
3、 在访问原子属性时,加互斥锁
1 - (void)sellTicketBy:(NSString *)name 2 { 3 while (YES) { 4 5 // 在访问原子属性的地方加互斥锁 6 @synchronized(self){ 7 if ([Tickets sharedTickets].num > 0) { 8 [Tickets sharedTickets].num--; 9 NSLog(@"剩余票数-%@-%d", name, [Tickets sharedTickets].num); 10 }else{ 11 NSLog(@"票卖完了"); 12 break; 13 } 14 } 15 16 // 让线程休眠,用于模拟售票员的效率不同 17 if ([name isEqualToString:@"p-1"]) { 18 [NSThread sleepForTimeInterval:1.0f]; 19 }else{ 20 [NSThread sleepForTimeInterval:0.5f]; 21 } 22 } 23 }
至此一个简单的模拟售票,处理多线程资源争夺的demo就完成了。
但是还有几点需要注意的:
1、互斥锁是非常消耗性能的,应该使加锁的内容越少越好
2、单例对象里应该重写copy、retain(非ARC)等方法,以防止团队里的其他人通过另类的方法创建单例对象。
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想
· Ai满嘴顺口溜,想考研?浪费我几个小时
· Browser-use 详细介绍&使用文档
· 智能Agent如何改造传统工作流:从搜索到全能助手