关注我,连载进行中....
什么情况会产生死锁! 下面这句话总结
使用 sync 函数往当前串行队列添加任务就会卡住当前的串行队列(产生死锁)
队列组的使用
// 创建队列组
dispatch_group_t group = dispatch_group_create();
// 创建并发队列
dispatch_queue_t queue = dispatch_queue_create("my_queue", DISPATCH_QUEUE_CONCURRENT);
// 添加异步任务
dispatch_group_async(group, queue, ^{
for (int i = 0; i < 5; i++) {
NSLog(@"任务1-%@", [NSThread currentThread]);
}
});
dispatch_group_async(group, queue, ^{
for (int i = 0; i < 5; i++) {
NSLog(@"任务2-%@", [NSThread currentThread]);
}
});
// 等前面的任务执行完毕后,会自动执行这个任务
dispatch_group_notify(group, queue, ^{
dispatch_async(dispatch_get_main_queue(), ^{
for (int i = 0; i < 5; i++) {
NSLog(@"任务3-%@", [NSThread currentThread]);
}
});
});
多线程的隐患
1: 1 块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源
2: 比如多个线程访问同一个对象,同一个变量,同一个文件
3:当多个线程访问同一块资源的时候,很容易引发数据错乱和数据安全问题
多线程安全隐患示例01 – 存钱取钱
图片.png
多线程安全隐患示例02 – 卖票
图片.png
上面是两个比较有代表性的多线程安全隐患示例:
大致解释一下. 比入存钱取钱. 1000 元是余额. 开启两条线程异步执行
开启一条线程,余额 1000, 存 1000 进去,然后对余额进行操作之后 然后余额是 2000
开启另外一条线程.余额: 1000. 取出 500 然后对余额进行操作之后是 500
本来最终的结果应该是 1000. 但是由于多线程的问题,就会导致 500 和 2000 的出现.
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self moneyTest];
}
/**
存钱、取钱演示
*/
- (void)moneyTest
{
self.money = 100;
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_async(queue, ^{
for (int i = 0; i < 10; i++) {
[self saveMoney];
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 10; i++) {
[self drawMoney];
}
});
}
/**
存钱
*/
- (void)saveMoney
{
int oldMoney = self.money;
sleep(.2);
oldMoney += 50;
self.money = oldMoney;
NSLog(@"存50,还剩%d元 - %@", oldMoney, [NSThread currentThread]);
}
/**
取钱
*/
- (void)drawMoney
{
int oldMoney = self.money;
sleep(.2);
oldMoney -= 20;
self.money = oldMoney;
NSLog(@"取20,还剩%d元 - %@", oldMoney, [NSThread currentThread]);
}
/**
卖1张票
*/
- (void)saleTicket
{
int oldTicketsCount = self.ticketsCount;
sleep(.2);
oldTicketsCount--;
self.ticketsCount = oldTicketsCount;
NSLog(@"还剩%d张票 - %@", oldTicketsCount, [NSThread currentThread]);
}
/**
卖票演示
*/
- (void)ticketTest
{
self.ticketsCount = 15;
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_async(queue, ^{
for (int i = 0; i < 5; i++) {
[self saleTicket];
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 5; i++) {
[self saleTicket];
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 5; i++) {
[self saleTicket];
}
});
}
存钱取钱.png
售票.png
怎么处理多线程问题
加锁
下面是一些常见的方案:
OSSpinLock
os_unfair_lock
pthread_mutex
dispatch_semaphore
dispatch_queue(DISPATCH_QUEUE_SERIAL)
NSLock
NSRecursiveLock
NSCondition
NSConditionLock
@synchronized
OSSpinLock叫做”自旋锁”,等待锁的线程会处于忙等(busy-wait)状态,一直占用着CPU资源
目前已经不再安全,可能会出现优先级反转问题
如果等待锁的线程优先级较高,它会一直占用着CPU资源,优先级低的线程就无法释放锁
需要导入头文件#import