iOS多线程编程——线程锁的使用

锁是多线程中中最常用的同步工具。
 在多线程编程中,不可避免的会遇到同一个资源在多个线程之间共同使用,这时候就需要通过加锁来保证线程的安全。
 1、@synchronized 互斥锁(性能较差;适用线程不多,任务量不大的多线程加锁)
 (1)加锁的代码尽量少
 (2)添加的OC对象必须在多个线程中都是同一对象
 (3)优点是不需要显式的创建锁对象,便可以实现锁的机制。
 (4)@synchronized块会隐式的添加一个异常处理例程来保护代码,该处理例程会在异常抛出的时候自动的释放互斥锁。所以如果不想让隐式的异常处理例程带来额外的开销,你可以考虑使用锁对象。
 2、NSLock 互斥锁(多次调用lock方法会造成死锁)
 (1)在Cocoa程序中NSLock中实现了一个简单的互斥锁。
 (2)所有锁(包括NSLock)的接口实际上都是通过NSLocking协议定义的,它定义了lock和unlock方法。你使用这些方法来获取和释放该锁。
 (3)NSLock类还增加了tryLock和lockBeforeDate:方法;tryLock试图获取一个锁,但是如果锁不可用的时候,它不会阻塞线程,相反,它只是返回NO。
 lockBeforeDate:方法试图获取一个锁,但是如果锁没有在规定的时间内被获得,它会让线程从阻塞状态变为非阻塞状态(或者返回NO)。
 3、NSRecursiveLock 递归锁(在递归或循环中使用递归锁;递归锁的性能出奇的高,但是只能作为递归使用,所以限制了使用场景)
 4、NSConditionLock 条件锁(加锁性能非常低,但是可以用来做多线程处理不同任务的通信调用)
 5、pthread_mutex 互斥锁(底层的api,复杂的多线程处理建议使用,并且可以封装自己的多线程)

 6、dispatch_semaphore 信号量

@interface Person : NSObject

@property (nonatomic, strong) NSString *name;

- (void)showMessage;

@end

@implementation Person

- (void)showMessage
{
    NSLog(@"%@, name is %@", [NSThread currentThread], self.name);
}

@end

- (void)threadSynchronized
{
    // 互斥锁 @synchronized 的使用,锁定的对象为锁的唯一标识,只有标识相同时,才满足互斥。
    NSLog(@"互斥锁");
    
    Person *person = [Person new];
    person.name = @"iosDev";
    
    Person *person2 = [Person new];
    person2.name = @"devZhang";
    
    // 线程A
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        @synchronized(person) {
            [person showMessage];
            [NSThread sleepForTimeInterval:3]; // 线程休眠3秒
        }
    });
    // 线程B
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        @synchronized(person) {
            [person showMessage];
        }
    });
    // 线程C
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        @synchronized(person2) {
            [person2 showMessage];
        }
    });
}
2018-03-07 14:43:43.972 DemoThread[1905:201544] {number = 9, name = (null)}, name is iosDev
2018-03-07 14:43:43.972 DemoThread[1905:201556] {number = 10, name = (null)}, name is devZhang
2018-03-07 14:43:46.974 DemoThread[1905:194520] {number = 11, name = (null)}, name is iosDev


- (void)threadNSLock
{
    // 互斥锁 NSLock 的使用,一个线程的执行需要等待另一个线程解锁后才开始。锁定(lock)和解锁(unLock)必须配对使用。
    NSLog(@"互斥锁");
    
    Person *person = [Person new];
    person.name = @"iosDev";
    
    Person *person2 = [Person new];
    person2.name = @"devZhang";
    
    // 创建锁
    NSLock *personLock = [NSLock new];
    
    // 线程A
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        @synchronized(person) {
            [personLock lock]; // 加锁
            [person showMessage];
            [NSThread sleepForTimeInterval:3]; // 线程休眠3秒
            [personLock unlock]; // 解锁
        }
    });
    // 线程B
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        @synchronized(person) {
            [personLock lock]; // 加锁
            [person showMessage];
            [personLock unlock]; // 解锁
        }
    });
    // 线程C
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        @synchronized(person2) {
            [person2 showMessage];
        }
    });
}

2018-03-07 14:44:19.925 DemoThread[1905:201556] {number = 10, name = (null)}, name is iosDev
2018-03-07 14:44:19.925 DemoThread[1905:202091] {number = 12, name = (null)}, name is devZhang
2018-03-07 14:44:22.930 DemoThread[1905:202090] {number = 13, name = (null)}, name is iosDev

- (void)threadNSRecursiveLock
{
    // 递归锁 NSRecursiveLock 的使用,在递归方法中使用递归锁,否则会造成死锁。
    NSLog(@"递归锁");
    
    Person *person = [Person new];
    person.name = @"iosDev";
    
    Person *person2 = [Person new];
    person2.name = @"devZhang";
    
    // 创建锁对象
    NSRecursiveLock *personLock = [[NSRecursiveLock alloc] init];
    
    // 创建递归方法
    static void (^testCode)(int);
    testCode = ^(int value) {
        [personLock lock];
        if (value > 0)
        {
            NSLog(@"递归0");
            [person showMessage];
            [NSThread sleepForTimeInterval:1];
            testCode(value - 1);
        }
        [personLock unlock];
    };
    
    // 线程A
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        testCode(5);
    });
    // 线程B
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [personLock lock];
        NSLog(@"递归1");
        [person showMessage];
        [personLock unlock];
    });
}

2018-03-07 14:44:47.007 DemoThread[1905:202091] 递归0
2018-03-07 14:44:47.007 DemoThread[1905:202091] {number = 12, name = (null)}, name is iosDev
2018-03-07 14:44:48.008 DemoThread[1905:202091] 递归0
2018-03-07 14:44:48.009 DemoThread[1905:202091] {number = 12, name = (null)}, name is iosDev
2018-03-07 14:44:49.012 DemoThread[1905:202091] 递归0
2018-03-07 14:44:49.013 DemoThread[1905:202091] {number = 12, name = (null)}, name is iosDev
2018-03-07 14:44:50.016 DemoThread[1905:202091] 递归0
2018-03-07 14:44:50.017 DemoThread[1905:202091] {number = 12, name = (null)}, name is iosDev
2018-03-07 14:44:51.019 DemoThread[1905:202091] 递归0
2018-03-07 14:44:51.019 DemoThread[1905:202091] {number = 12, name = (null)}, name is iosDev
2018-03-07 14:44:52.020 DemoThread[1905:202411] 递归1
2018-03-07 14:44:52.020 DemoThread[1905:202411] {number = 14, name = (null)}, name is iosDev

- (void)threadCondition
{
    // 条件锁 NSConditionLock 的使用,只有满足条件的时候才可以解锁。
    NSLog(@"条件锁");
    
    Person *person = [Person new];
    person.name = @"iosDev";
    
    Person *person2 = [Person new];
    person2.name = @"devZhang";
    
    // 创建锁对象
    NSConditionLock *personLock = [[NSConditionLock alloc] init];
    
    // 线程A
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [personLock lock]; // 加锁
        [person showMessage];
        [NSThread sleepForTimeInterval:3];
        [personLock unlockWithCondition:10]; // 符合条件时解锁
    });
    // 线程B
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [personLock lockWhenCondition:10]; // 符合条件时加锁
        [person showMessage];
        [personLock unlock]; // 解锁
    });
}

2018-03-07 14:45:22.072 DemoThread[1905:202412] {number = 15, name = (null)}, name is iosDev
2018-03-07 14:45:25.077 DemoThread[1905:202887] {number = 16, name = (null)}, name is iosDev

- (void)threadCMethod
{
    // C语言方法实现加锁
    // 互斥锁
    // 互斥锁 + 条件锁
    // #import 
    
    Person *person = [Person new];
    person.name = @"iosDev";
    
    Person *person2 = [Person new];
    person2.name = @"devZhang";
    
    // 创建锁对象
    NSLog(@"互斥锁");
    // 互斥锁
    __block pthread_mutex_t personlock;
    pthread_mutex_init(&personlock, NULL);
    
    // 线程A
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        pthread_mutex_lock(&personlock); // 加锁
        [person showMessage];
        [NSThread sleepForTimeInterval:3];
        pthread_mutex_unlock(&personlock); // 解锁
    });
    // 线程B
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        pthread_mutex_lock(&personlock);
        [person showMessage];
        pthread_mutex_unlock(&personlock);
    });
    
    NSLog(@"互斥锁 + 条件锁");
    // 互斥锁 + 条件锁
    __block pthread_cond_t personCodition;
    pthread_cond_init(&personCodition, NULL);
    
    // 线程A
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        pthread_mutex_lock(&personlock); // 加锁
        pthread_cond_wait(&personCodition, &personlock); // 条件锁
        [person showMessage];
        pthread_mutex_unlock(&personlock); // 解锁
    });
    // 线程B
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        pthread_mutex_lock(&personlock);
        [person showMessage];
        pthread_cond_signal(&personCodition); // 条件锁
        [NSThread sleepForTimeInterval:3];
        pthread_mutex_unlock(&personlock);
    });
}

2018-03-07 14:46:07.545 DemoThread[1905:202888] {number = 17, name = (null)}, name is iosDev
2018-03-07 14:46:10.548 DemoThread[1905:203469] {number = 18, name = (null)}, name is iosDev
2018-03-07 14:46:10.548 DemoThread[1905:203471] {number = 19, name = (null)}, name is iosDev
2018-03-07 14:46:13.552 DemoThread[1905:203470] {number = 20, name = (null)}, name is iosDev

- (void)threadGCD
{
    // 使用 GCD 实现 “ 锁 ” (信号量)  GCD提供一种信号的机制,使用它我们可以创建“锁”(信号量和锁是有区别的,具体请自行百度)。
    
    Person *person = [Person new];
    person.name = @"iosDev";
    
    Person *person2 = [Person new];
    person2.name = @"devZhang";
    
    // 创建并设置信量
    dispatch_semaphore_t personGCD = dispatch_semaphore_create(1);
    
    // 线程A
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        dispatch_semaphore_wait(personGCD, DISPATCH_TIME_FOREVER); // 等待信号
        [person showMessage];
        [NSThread sleepForTimeInterval:3];
        dispatch_semaphore_signal(personGCD); // 发送信号
    });
    // 线程B
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        dispatch_semaphore_wait(personGCD, DISPATCH_TIME_FOREVER); // 等待信号
        [person showMessage];
        dispatch_semaphore_signal(personGCD); // 发送信号
    });
}

2018-03-07 14:46:41.194 DemoThread[1905:203472] {number = 21, name = (null)}, name is iosDev
2018-03-07 14:46:44.194 DemoThread[1905:203982] {number = 22, name = (null)}, name is iosDev





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