线程安全隐患的解决方案

249 阅读4分钟
#import "ViewController.h"
@interface ViewController ()
@property(assign,nonatomic)NSInteger ticketCount;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self moneyTest];
}

/**
 存钱,取钱演示
 */
- (void)moneyTest {
    self.ticketCount = 20;
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    dispatch_async(queue, ^{
        for (int i = 0; i < 10; i++) {
            [self saleTickets];
        }
    });
    dispatch_async(queue, ^{
        for (int i = 0; i < 10; i++) {
            [self saleTickets];
        }
    });

}

- (void)saleTickets {
    NSInteger oldCount = self.ticketCount;
    sleep(.2);
    oldCount--;
    self.ticketCount = oldCount;
    NSLog(@"还剩%ld",(long)self.ticketCount);
}
打印
2020-03-24 10:18:32.343352+0800 多线程[97991:1912112] 还剩19
2020-03-24 10:18:32.343352+0800 多线程[97991:1912111] 还剩19
2020-03-24 10:18:32.343569+0800 多线程[97991:1912111] 还剩18
2020-03-24 10:18:32.343569+0800 多线程[97991:1912112] 还剩18
2020-03-24 10:18:32.343679+0800 多线程[97991:1912112] 还剩17
2020-03-24 10:18:32.343679+0800 多线程[97991:1912111] 还剩17
2020-03-24 10:18:32.343782+0800 多线程[97991:1912111] 还剩16
2020-03-24 10:18:32.343782+0800 多线程[97991:1912112] 还剩16
2020-03-24 10:18:32.343886+0800 多线程[97991:1912111] 还剩15
2020-03-24 10:18:32.346031+0800 多线程[97991:1912112] 还剩14
2020-03-24 10:18:32.346725+0800 多线程[97991:1912111] 还剩13
2020-03-24 10:18:32.347467+0800 多线程[97991:1912112] 还剩12
2020-03-24 10:18:32.350891+0800 多线程[97991:1912111] 还剩11
2020-03-24 10:18:32.352777+0800 多线程[97991:1912112] 还剩10
2020-03-24 10:18:32.358585+0800 多线程[97991:1912111] 还剩9
2020-03-24 10:18:32.364403+0800 多线程[97991:1912112] 还剩8
2020-03-24 10:18:32.366631+0800 多线程[97991:1912111] 还剩7
2020-03-24 10:18:32.367975+0800 多线程[97991:1912112] 还剩6
2020-03-24 10:18:32.369269+0800 多线程[97991:1912111] 还剩5
2020-03-24 10:18:32.370106+0800 多线程[97991:1912112] 还剩4


解决方案:使用线程同步技术(同步,就是协同步调,按预先的先后次序进行运行)

常见的线程同步技术是:加锁

OSSpinLock 自旋锁,等待锁的线程处于忙等状态,一直占有cpu资源 导入 #import <libkern/OSAtomic.h>框架

#import "ViewController.h"
#import <libkern/OSAtomic.h>
@interface ViewController ()
@property(assign,nonatomic)NSInteger ticketCount;
@property(assign,nonatomic)OSSpinLock lock;//锁
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self moneyTest];
}

/**
 存钱,取钱演示
 */
- (void)moneyTest {
    
    self.ticketCount = 10;
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    dispatch_async(queue, ^{
        for (int i = 0; i < 5; i++) {
            [self saleTickets];
        }
    });
    dispatch_async(queue, ^{
        for (int i = 0; i < 5; i++) {
            [self saleTickets];
        }
    });
}

- (void)saleTickets {
    //初始化锁
    _lock = OS_SPINLOCK_INIT;
    //加锁
    OSSpinLockLock(&_lock);
    
    NSInteger oldCount = self.ticketCount;
    sleep(.2);
    oldCount--;
    self.ticketCount = oldCount;
    NSLog(@"还剩%ld",(long)self.ticketCount);
    OSSpinLockUnlock(&_lock);
}
2020-03-24 10:35:35.447204+0800 多线程[99261:1939794] 还剩9
2020-03-24 10:35:35.447468+0800 多线程[99261:1939794] 还剩8
2020-03-24 10:35:35.447597+0800 多线程[99261:1939794] 还剩7
2020-03-24 10:35:35.447716+0800 多线程[99261:1939794] 还剩6
2020-03-24 10:35:35.447832+0800 多线程[99261:1939794] 还剩5
2020-03-24 10:35:35.448194+0800 多线程[99261:1939797] 还剩4
2020-03-24 10:35:35.449809+0800 多线程[99261:1939797] 还剩3
2020-03-24 10:35:35.449952+0800 多线程[99261:1939797] 还剩2
2020-03-24 10:35:35.450070+0800 多线程[99261:1939797] 还剩1
2020-03-24 10:35:35.450280+0800 多线程[99261:1939797] 还剩0