概述
多线程的本质就是CPU轮流随机分配给每条线程时间片资源执行任务,看起来多条线程同时执行任务。
多条线程同时访问同一块资源,比如操作同一个对象、统一变量、同一个文件,就会引发数据错乱和数据安全
的问题。
多线程引发问题实例
这里我也借助网上两个比较经典的案例,卖票和存取钱。
卖票案例
多个线程同时卖票,同一时间多个线层同时访问票的总数,就会引发数据错乱。
实例代码
@interface ViewController ()
@property (nonatomic, assign) int tickets;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tickets = 30;
[self saleTicketTest];
}
- (void)saleTicketWithName:(NSString *)name
{
int currTicketCount = self.tickets;
sleep(.2);
currTicketCount--;
self.tickets = currTicketCount;
NSLog(@"当前%@卖了一张,票还剩:%d张", name ,self.tickets);
}
- (void)saleTicketTest
{
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_async(queue, ^{
for (int i=0; i<10; i++) {
[self saleTicketWithName:@"A"];
}
});
dispatch_async(queue, ^{
for (int i=0; i<10; i++) {
[self saleTicketWithName:@"B"];
}
});
dispatch_async(queue, ^{
for (int i=0; i<10; i++) {
[self saleTicketWithName:@"C"];
}
});
}
@end
异常结果:
存钱取钱案例
实例代码
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, assign) int currMoney;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.currMoney = 1000;
[self moneyTest];
}
- (void)moneyTest
{
dispatch_async(dispatch_get_global_queue(0, 0), ^{
for (int i=0; i<4; i++) {
[self saveMoney];
}
});
dispatch_async(dispatch_get_global_queue(0, 0), ^{
for (int i=0; i<4; i++) {
[self drawMoney];
}
});
}
// 存钱
- (void)saveMoney
{
int money = self.currMoney;
sleep(.3);
money += 100;
self.currMoney = money;
NSLog(@"存了100,还剩%d元", self.currMoney);
}
// 取钱
- (void)drawMoney
{
int money = self.currMoney;
sleep(.3);
money -= 50;
self.currMoney = money;
NSLog(@"取了50,还剩%d元", self.currMoney);
}
异常结果:
多线程安全隐患的解决方案
开发中解决多线程安全隐患的方案-使用线程同步技术。同步(协同步调,按预定的先后顺序执行)
常见的线程同步技术就是加锁
。
iOS中线程同步的方案根据性能优先级排序:
线程同步的方案 | 需要导入头文件 | 类别 | 注意事项 |
---|---|---|---|
os_unfair_lock | <os/lock.h> | 互斥锁 | iOS10才开始提供,用来替代OSSpinLock |
OSSpinLock | <libkern/OSAtomic.h> | 自旋锁 | 目前不在安全,可能会出现优先级反转问题 |
dispatch_semaphore | |||
pthread_mutex | |||
dispatch_queue(DISPATCH_SENTINEL) | |||
NSLock | |||
oNSCondition | <os/lock.h> | ||
pthread_mutex(recuresive) | |||
NSRecursiveLock | |||
NSConditionLock | |||
@synchronized |