多线程(三)

上篇多线程(二)我们看了多线程的死锁和队列组的使用,下面我们再来看看多线程的安全隐患
代码详见 gitHub_Demo


多线程的安全隐患

多线程(三)_第1张图片
Multithreading_15.png

存钱/取钱

多线程(三)_第2张图片
Multithreading_16.png

卖票

多线程(三)_第3张图片
Multithreading_17.png

代码演示

#import "ViewController_6.h"
@interface ViewController_6 ()
@property (assign, nonatomic) int ticketsCount;
@property (assign, nonatomic) int money;
@end

@implementation ViewController_6
- (void)viewDidLoad {
    [super viewDidLoad];
    [self moneyTest];
    [self ticketTest];
}

/**
  存钱、取钱演示
  */
- (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];
        }
    });
}
@end

多线程安全隐患分析

多线程(三)_第4张图片
Multithreading_18.png

多线程安全隐患的解决方案

多线程(三)_第5张图片
Multithreading_19.png

iOS中的线程同步方案

多线程(三)_第6张图片
Multithreading_20.png

OSSpinLock 不再安全的 OSSpinLock

多线程(三)_第7张图片
Multithreading_21.png
#import "ViewController_7.h"
#import 

@interface ViewController_7 ()
@property (assign, nonatomic) int money;
@property (assign, nonatomic) int ticketsCount;
@property (assign, nonatomic) OSSpinLock lock;
@property (assign, nonatomic) OSSpinLock lock1;
@end

@implementation ViewController_7

- (void)viewDidLoad {
    [super viewDidLoad];
    // 初始化锁
    self.lock = OS_SPINLOCK_INIT;
    self.lock1 = OS_SPINLOCK_INIT;
    [self ticketTest];
    [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{
    // 加锁
    OSSpinLockLock(&_lock1);
    int oldMoney = self.money;
    sleep(.2);
    oldMoney += 50;
    self.money = oldMoney;
    NSLog(@"存50,还剩%d元 - %@", oldMoney, [NSThread currentThread]);
    // 解锁
    OSSpinLockUnlock(&_lock1);
}

/**
  取钱
  */
- (void)drawMoney{
    // 加锁
    OSSpinLockLock(&_lock1);
    int oldMoney = self.money;
    sleep(.2);
    oldMoney -= 20;
    self.money = oldMoney;
    NSLog(@"取20,还剩%d元 - %@", oldMoney, [NSThread currentThread]);
    // 解锁
    OSSpinLockUnlock(&_lock1);
}

/**
  卖1张票
  */
- (void)saleTicket{
    // 加锁
    OSSpinLockLock(&_lock);
    int oldTicketsCount = self.ticketsCount;
    sleep(.2);
    oldTicketsCount--;
    self.ticketsCount = oldTicketsCount;
    NSLog(@"还剩%d张票 - %@", oldTicketsCount, [NSThread currentThread]);
    // 解锁
    OSSpinLockUnlock(&_lock);
}

/**
  卖票演示
  */
- (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];
        }
    });
}
@end

弊端:会出现优先级反转(感兴趣的自己可以细入研究)

补充:

只【当前文件】可以访问(static),全局变量初始化最好放在initialize里面(用到的时候在初始化),如:
static OSSpinLock moneyLock_; //下划线在后面(全局变量)
+ (void)initialize{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        moneyLock_ = 0;
    });
}

static NSString  *A = @"1111"; //可以
static NSString  *A = test(); //不可以 (函数调用了,函数是在运行的时候执行的)(static是在编译的时候)
解决:
  static NSString *str = nil;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
        str = test();
  });

os_unfair_lock

多线程(三)_第8张图片
Multithreading_22.png
YDBaseDemo.h
#import 
@interface YDBaseDemo : NSObject
- (void)moneyTest;
- (void)ticketTest;
#pragma mark - 暴露给子类去使用
- (void)__saveMoney;
- (void)__drawMoney;
- (void)__saleTicket;
@end

YDBaseDemo.m
#import "YDBaseDemo.h"
@interface YDBaseDemo()
@property (assign, nonatomic) int money;
@property (assign, nonatomic) int ticketsCount;
@end

@implementation YDBaseDemo
/**
  存钱、取钱演示
  */
- (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];
        }
    });
}
@end

OSUnfairLockDemo.h
#import "YDBaseDemo.h"
@interface OSUnfairLockDemo : YDBaseDemo
@end

OSUnfairLockDemo.m
#import "OSUnfairLockDemo.h"
#import 
@interface OSUnfairLockDemo()
// Low-level lock的特点等不到锁就休眠
@property (assign, nonatomic) os_unfair_lock moneyLock;
@property (assign, nonatomic) os_unfair_lock ticketLock;
@end

@implementation OSUnfairLockDemo
- (instancetype)init{
    if (self = [super init]) {
        self.moneyLock = OS_UNFAIR_LOCK_INIT;
        self.ticketLock = OS_UNFAIR_LOCK_INIT;
    }
    return self;
}
- (void)__saleTicket{
    os_unfair_lock_lock(&_ticketLock);
    [super __saleTicket];
    os_unfair_lock_unlock(&_ticketLock);
}
- (void)__saveMoney{
    os_unfair_lock_lock(&_moneyLock);
    [super __saveMoney];
    os_unfair_lock_unlock(&_moneyLock);
}
- (void)__drawMoney{
    os_unfair_lock_lock(&_moneyLock);
    [super __drawMoney];
    os_unfair_lock_unlock(&_moneyLock);
}
@end

调用:
  OSUnfairLockDemo *demo = [[OSUnfairLockDemo  alloc]init];
  [demo ticketTest];
  [demo moneyTest];

pthread_mutex

多线程(三)_第9张图片
Multithreading_23.png
MutexDemo.h
#import "YDBaseDemo.h"
@interface MutexDemo : YDBaseDemo
@end

MutexDemo.m
#import "MutexDemo.h"
#import 

@interface MutexDemo()
@property (assign, nonatomic) pthread_mutex_t ticketMutex;
@property (assign, nonatomic) pthread_mutex_t moneyMutex;
@end

@implementation MutexDemo
- (void)__initMutex:(pthread_mutex_t *)mutex{
    // 初始化锁
    pthread_mutex_init(mutex, NULL); //传入空就是Default
}
- (instancetype)init{
    if (self = [super init]) {
        [self __initMutex:&_ticketMutex];
        [self __initMutex:&_moneyMutex];
    }
    return self;
}
- (void)__saleTicket{
    pthread_mutex_lock(&_ticketMutex);
    [super __saleTicket];
    pthread_mutex_unlock(&_ticketMutex);
}
- (void)__saveMoney{
    pthread_mutex_lock(&_moneyMutex);
    [super __saveMoney];
    pthread_mutex_unlock(&_moneyMutex);
}
- (void)__drawMoney{
    pthread_mutex_lock(&_moneyMutex);
    [super __drawMoney];
    pthread_mutex_unlock(&_moneyMutex);
}
- (void)dealloc{
    pthread_mutex_destroy(&_moneyMutex);
    pthread_mutex_destroy(&_ticketMutex);
}
@end

调用:
 MutexDemo *demo = [[MutexDemo alloc]init];
 [demo ticketTest];
 [demo moneyTest];

pthread_mutex – 递归锁

#import "MutexDemo2.h"
#import 
@interface MutexDemo2()
@property (assign, nonatomic) pthread_mutex_t mutex;
@end

@implementation MutexDemo2
- (void)__initMutex:(pthread_mutex_t *)mutex{
    // 递归锁:允许同一个线程对一把锁进行重复加锁
    
    // 初始化属性
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
    // 初始化锁
    pthread_mutex_init(mutex, &attr);
    // 销毁属性
    pthread_mutexattr_destroy(&attr);
}

- (instancetype)init{
    if (self = [super init]) {
        [self __initMutex:&_mutex];
    }
    return self;
}

/**
  线程1:otherTest(+-)
         otherTest(+-)
          otherTest(+-)
  
  线程2:otherTest(等待)
 */
- (void)otherTest{
    pthread_mutex_lock(&_mutex);
    NSLog(@"%s", __func__);
    static int count = 0;
    NSLog(@"%d",count);
    if (count < 10) {
        count++;
        [self otherTest];
    }
    pthread_mutex_unlock(&_mutex);
}
- (void)dealloc{
    NSLog(@"%s", __func__);
    pthread_mutex_destroy(&_mutex);
}
@end

pthread_mutex – 条件

多线程(三)_第10张图片
Multithreading_24.png

#import "MutexDemo3.h"
#import 
@interface MutexDemo3()
@property (assign, nonatomic) pthread_mutex_t mutex;
@property (assign, nonatomic) pthread_cond_t cond;
@property (strong, nonatomic) NSMutableArray *data;
@end

@implementation MutexDemo3
- (instancetype)init{
    if (self = [super init]) {
        // 初始化属性
        pthread_mutexattr_t attr;
        pthread_mutexattr_init(&attr);
        pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
        // 初始化锁
        pthread_mutex_init(&_mutex, &attr);
        // 销毁属性
        pthread_mutexattr_destroy(&attr);
        // 初始化条件
        pthread_cond_init(&_cond, NULL);
        self.data = [NSMutableArray array];
    }
    return self;
}

- (void)otherTest{
    [[[NSThread alloc] initWithTarget:self selector:@selector(__remove) object:nil] start];
    [[[NSThread alloc] initWithTarget:self selector:@selector(__add) object:nil] start];
}

// 生产者-消费者模式
// 线程1
// 删除数组中的元素
- (void)__remove{
    pthread_mutex_lock(&_mutex);
    NSLog(@"__remove - begin");
    if (self.data.count == 0) {
        // 等待
        pthread_cond_wait(&_cond, &_mutex); //等待的时候,会放开此时的锁
    }
    [self.data removeLastObject];
    NSLog(@"删除了元素");
    pthread_mutex_unlock(&_mutex);
}

// 线程2
// 往数组中添加元素
- (void)__add{
    pthread_mutex_lock(&_mutex);
    sleep(1);
    [self.data addObject:@"Test"];
    NSLog(@"添加了元素");
    // 信号
    pthread_cond_signal(&_cond);//唤醒线程
    // 广播
    //pthread_cond_broadcast(&_cond); //一次性唤醒多个线程
    pthread_mutex_unlock(&_mutex);
    NSLog(@"--");
}

- (void)dealloc{
    pthread_mutex_destroy(&_mutex);
    pthread_cond_destroy(&_cond);
}
@end

NSLock、NSRecursiveLock

多线程(三)_第11张图片
Multithreading_25.png
NSLockDemo.h
#import "YDBaseDemo.h"
@interface NSLockDemo : YDBaseDemo
@end

NSLockDemo.m
#import "NSLockDemo.h"
@interface NSLockDemo()
@property (strong, nonatomic) NSLock *ticketLock;
@property (strong, nonatomic) NSLock *moneyLock;
@end

@implementation NSLockDemo
- (instancetype)init{
    if (self = [super init]) {
        self.ticketLock = [[NSLock alloc] init];
        self.moneyLock = [[NSLock alloc] init];
    }
    return self;
}

- (void)__saleTicket{
    [self.ticketLock lock];
    [super __saleTicket];
    [self.ticketLock unlock];
}

- (void)__saveMoney{
    [self.moneyLock lock];
    [super __saveMoney];
    [self.moneyLock unlock];
}

- (void)__drawMoney{
    [self.moneyLock lock];
    [super __drawMoney];
    [self.moneyLock unlock];
}
@end

调用:
NSLockDemo *demo = [[NSLockDemo alloc]init];
[demo ticketTest];
[demo moneyTest];

NSCondition

多线程(三)_第12张图片
Multithreading_26.png
#import "NSConditionDemo.h"
@interface NSConditionDemo()
@property (strong, nonatomic) NSCondition *condition;
@property (strong, nonatomic) NSMutableArray *data;
@end

@implementation NSConditionDemo
- (instancetype)init{
    if (self = [super init]) {
        self.condition = [[NSCondition alloc] init];
        self.data = [NSMutableArray array];
    }
    return self;
}

- (void)otherTest{
    [[[NSThread alloc] initWithTarget:self selector:@selector(__remove) object:nil] start];
    [[[NSThread alloc] initWithTarget:self selector:@selector(__add) object:nil] start];
}

// 生产者-消费者模式

// 线程1
// 删除数组中的元素
- (void)__remove{
    [self.condition lock];
    NSLog(@"__remove - begin");
    if (self.data.count == 0) {
        // 等待
        [self.condition wait];
    }
    [self.data removeLastObject];
    NSLog(@"删除了元素");
    [self.condition unlock];
}

// 线程2
// 往数组中添加元素
- (void)__add{
    [self.condition lock];
    sleep(1);
    [self.data addObject:@"Test"];
    NSLog(@"添加了元素");
    // 信号
    [self.condition signal];
    // 广播
    //    [self.condition broadcast];
    [self.condition unlock];
    
    // <==>(这样就无需等待解锁了)
    // [self.condition unlock];
    // [self.condition signal];
}
@end

NSConditionLock

多线程(三)_第13张图片
Multithreading_27.png

#import "NSConditionLockDemo.h"
@interface NSConditionLockDemo()
@property (strong, nonatomic) NSConditionLock *conditionLock;
@end

@implementation NSConditionLockDemo
- (instancetype)init{
    if (self = [super init]) {
        self.conditionLock = [[NSConditionLock alloc] initWithCondition:1];
    }
    return self;
}

- (void)otherTest{
    [[[NSThread alloc] initWithTarget:self selector:@selector(__one) object:nil] start];
    [[[NSThread alloc] initWithTarget:self selector:@selector(__two) object:nil] start];
    [[[NSThread alloc] initWithTarget:self selector:@selector(__three) object:nil] start];
}

- (void)__one{
    [self.conditionLock lock];
    NSLog(@"__one");
    sleep(1);
    [self.conditionLock unlockWithCondition:2];
}

- (void)__two{
    [self.conditionLock lockWhenCondition:2];
    NSLog(@"__two");
    sleep(1);
    [self.conditionLock unlockWithCondition:3];
}

- (void)__three{
    [self.conditionLock lockWhenCondition:3];
    NSLog(@"__three");
    [self.conditionLock unlock];
}
@end

SerialQueue

多线程(三)_第14张图片
Multithreading_28.png
YDBaseDemo.h
#import 
@interface YDBaseDemo : NSObject
- (void)moneyTest;
- (void)ticketTest;
#pragma mark - 暴露给子类去使用
- (void)__saveMoney;
- (void)__drawMoney;
- (void)__saleTicket;
@end

YDBaseDemo.m
#import "YDBaseDemo.h"
@interface YDBaseDemo()
@property (assign, nonatomic) int money;
@property (assign, nonatomic) int ticketsCount;
@end

@implementation YDBaseDemo
/**
  存钱、取钱演示
  */
- (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];
        }
    });
}
@end

SerialQueueDemo.h
#import "YDBaseDemo.h"
@interface SerialQueueDemo : YDBaseDemo
@end

SerialQueueDemo.m
#import"SerialQueueDemo.h"
@interface SerialQueueDemo()
@property (strong, nonatomic) dispatch_queue_t ticketQueue;
@property (strong, nonatomic) dispatch_queue_t moneyQueue;
@end

@implementation SerialQueueDemo
- (instancetype)init{
    if (self = [super init]) {
        self.ticketQueue = dispatch_queue_create("ticketQueue", DISPATCH_QUEUE_SERIAL);
        self.moneyQueue = dispatch_queue_create("moneyQueue", DISPATCH_QUEUE_SERIAL);
    }
    return self;
}

- (void)__drawMoney{
    dispatch_sync(self.moneyQueue, ^{
        [super __drawMoney];
    });
}

- (void)__saveMoney{
    dispatch_sync(self.moneyQueue, ^{
        [super __saveMoney];
    });
}

- (void)__saleTicket{
    dispatch_sync(self.ticketQueue, ^{
        [super __saleTicket];
    });
}
@end
多线程(三)_第15张图片
Multithreading_29.png

dispatch_semaphore

多线程(三)_第16张图片
Multithreading_30.png
SemaphoreDemo.h
#import "YDBaseDemo.h"
@interface SemaphoreDemo : YDBaseDemo
- (void)otherTest;
@end

SemaphoreDemo.m
#import "SemaphoreDemo.h"
@interface SemaphoreDemo()
@property (strong, nonatomic) dispatch_semaphore_t semaphore;
@property (strong, nonatomic) dispatch_semaphore_t ticketSemaphore;
@property (strong, nonatomic) dispatch_semaphore_t moneySemaphore;
@end

@implementation SemaphoreDemo

- (instancetype)init{
    if (self = [super init]) {
        self.semaphore = dispatch_semaphore_create(5);
        self.ticketSemaphore = dispatch_semaphore_create(1);
        self.moneySemaphore = dispatch_semaphore_create(1);
    }
    return self;
}

- (void)__drawMoney{
    dispatch_semaphore_wait(self.moneySemaphore, DISPATCH_TIME_FOREVER);
    [super __drawMoney];
    dispatch_semaphore_signal(self.moneySemaphore);
}

- (void)__saveMoney{
//    sleep(1);
    dispatch_semaphore_wait(self.moneySemaphore, DISPATCH_TIME_FOREVER);
    [super __saveMoney];
    dispatch_semaphore_signal(self.moneySemaphore);
}

- (void)__saleTicket{
    dispatch_semaphore_wait(self.ticketSemaphore, DISPATCH_TIME_FOREVER);
    [super __saleTicket];
    dispatch_semaphore_signal(self.ticketSemaphore);
}

- (void)otherTest{
    for (int i = 0; i < 20; i++) {
        [[[NSThread alloc] initWithTarget:self selector:@selector(test) object:nil] start];
    }
}

// 线程10、7、6、9、8
- (void)test{
    // 如果信号量的值 > 0,就让信号量的值减1,然后继续往下执行代码
    // 如果信号量的值 <= 0,就会休眠等待,直到信号量的值变成>0,就让信号量的值减1,然后继续往下执行代码
    dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
    sleep(2);
    NSLog(@"test - %@", [NSThread currentThread]);
    // 让信号量的值+1
    dispatch_semaphore_signal(self.semaphore);
}
@end

调用:
SemaphoreDemo *demo = [[SemaphoreDemo alloc]init];
[demo moneyTest];
[demo ticketTest];
[demo otherTest];
多线程(三)_第17张图片
Multithreading_31.png

@synchronized

多线程(三)_第18张图片
Multithreading_32.png
下载runtime源码【objc4-750】 在objc-sync.mm文件里面发现 
// Begin synchronizing on 'obj'. 
// Allocates recursive mutex associated with 'obj' if needed.
// Returns OBJC_SYNC_SUCCESS once lock is acquired.  
int objc_sync_enter(id obj)
{
    int result = OBJC_SYNC_SUCCESS;
    if (obj) {
        SyncData* data = id2data(obj, ACQUIRE);
        assert(data);
        data->mutex.lock();
    } else {
        // @synchronized(nil) does nothing
        if (DebugNilSync) {
            _objc_inform("NIL SYNC DEBUG: @synchronized(nil); set a breakpoint on objc_sync_nil to debug");
        }
        objc_sync_nil();
    }
    return result;
}


// End synchronizing on 'obj'. 
// Returns OBJC_SYNC_SUCCESS or OBJC_SYNC_NOT_OWNING_THREAD_ERROR
int objc_sync_exit(id obj)
{
    int result = OBJC_SYNC_SUCCESS;
    if (obj) {
        SyncData* data = id2data(obj, RELEASE); 
        if (!data) {
            result = OBJC_SYNC_NOT_OWNING_THREAD_ERROR;
        } else {
            bool okay = data->mutex.tryUnlock();
            if (!okay) {
                result = OBJC_SYNC_NOT_OWNING_THREAD_ERROR;
            }
        }
    } else {
        // @synchronized(nil) does nothing
    }
    return result;
}
SynchronizedDemo.h
#import "YDBaseDemo.h"
@interface SynchronizedDemo : YDBaseDemo
- (void)otherTest;
@end

SynchronizedDemo.m
#import "SynchronizedDemo.h"
@implementation SynchronizedDemo
- (void)__drawMoney{
    @synchronized([self class]) {
        [super __drawMoney];
    }
}

- (void)__saveMoney{
    @synchronized([self class]) { // objc_sync_enter
        [super __saveMoney];
    } // objc_sync_exit
}

- (void)__saleTicket{
    static NSObject *lock;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        lock = [[NSObject alloc] init];
    });
    @synchronized(lock) {
        [super __saleTicket];
    }
}

- (void)otherTest{
    static int i = 0;
    @synchronized([self class]) {
        I++;
        NSLog(@"i=%d",i);
        if(i==10){
            NSLog(@"over");
        }else{
             [self otherTest];
        }
    }
}
@end

友情链接:

  • gitHub_Demo

  • 多线程(一)

  • 多线程(二)

  • 多线程(四)

你可能感兴趣的:(多线程(三))