美文网首页
iOS中常见的锁

iOS中常见的锁

作者: alvin_wang | 来源:发表于2017-12-21 11:01 被阅读21次

锁一般用于在多线程中,保证在一段时期内这段代码只能被某一个线程所访问,从而保证线程同步。在iOS中,常用的锁大致有@synchronized,NSLock,NSCondition,NSConditionLock、NSRecursiveLock和dispatch_semaphore等,如下图所示。


image.png
1. 常见锁介绍

锁按照功能分,主要可以分为互斥锁,自旋锁,信号量。

  • 互斥锁禁止多个线程同时进入受保护的代码“临界区”(critical section)。
  • 自旋锁跟互斥锁一样,但是获取锁操作将自旋在那里,直到该自旋锁的保持者释放了锁。
  • 信号量是一个计数器,它用来记录对某个资源(如共享内存)的存取状况。
1.1 @synchronized

@synchronized(obj)指令使用的obj为该锁的唯一标识,同一标识的线程互斥。这是通过一个哈希表来实现的,OC 在底层使用了一个互斥锁的数组(你可以理解为锁池),通过对对象去哈希值来得到对应的互斥锁。@synchronized的内部详细原理可以参考关于 @synchronized,这儿比你想知道的还要多

NSMutableArray *arr = [NSMutableArray arrayWithObjects:@1,@2, nil];

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    sleep(1);
    @synchronized(arr) {
        [arr removeLastObject];
        sleep(1);
        NSLog(@"%lu in thread1",arr.count);

    }
});

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    @synchronized(arr) {
        @synchronized(arr) {
            [arr removeLastObject];
            NSLog(@"%lu in thread2",arr.count);
            sleep(2);
        }
    }
});

输出结果如下:

2017-12-20 14:55:19.646387+0800 Lock[49276:6948973] 1 in thread2
2017-12-20 14:55:22.653366+0800 Lock[49276:6948972] 0 in thread1
1.2 NSConditon

NSConditon是一种条件锁。当其他线程的锁收到signal(单发)或者broadcast(多发)时,如果条件为true,则会上锁。

NSCondition *lock = [[NSCondition alloc] init];
NSMutableArray *array = [[NSMutableArray alloc] init];

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    [lock lock];
    while (!array.count) {
        [lock wait];
    }
    [array removeLastObject];
    NSLog(@"remove last object %@",array);
    [lock unlock];
});

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    [lock lock];
    while (!array.count) {
        [lock wait];
    }
    [array removeLastObject];
    NSLog(@"remove last object %@",array);
    [lock unlock];
});

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    sleep(1);
    [lock lock];
    [array addObjectsFromArray:@[@1,@2]];
    NSLog(@"add objects @1,@2");
    [lock broadcast];
    [lock unlock];
});
}

输出如下:

2017-12-20 15:09:27.322078+0800 Lock[67589:7008671] add objects @1,@2
2017-12-20 15:09:27.322539+0800 Lock[67589:7008668] remove last object (
1
)
2017-12-20 15:09:27.322731+0800 Lock[67589:7008669] remove last object (
)
1.3 NSConditionLock

NSConditionLock这种条件锁在初始化时可以指定一个条件,在上锁时,只有满足这个条件才能上锁,在解锁时,可以修改这个条件锁的条件。

NSConditionLock *lock = [[NSConditionLock alloc] initWithCondition:1];

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    [lock lockWhenCondition:0];
    NSLog(@"locked this lock in thread 1");
    sleep(1);
    [lock unlock];
});

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    sleep(2);
    if ([lock tryLockWhenCondition:1]) {
        NSLog(@"locked this lock in thread 2");
        sleep(1);
        [lock unlockWithCondition:0];
        NSLog(@"unlocked this lock in thread 2");
    } else {
        NSLog(@"fail locked this lock in thread 2");
    }
});

输出如下:

2017-12-20 15:16:32.725752+0800 Lock[76697:7037383] locked this lock in thread 2
2017-12-20 15:16:33.726779+0800 Lock[76697:7037383] unlocked this lock in thread 2
2017-12-20 15:16:33.726803+0800 Lock[76697:7037384] locked this lock in thread 1
1.4 NSRecursiveLock

递归锁用在需要递归的地方。这种锁不会因为重复上锁而导致死锁。

NSRecursiveLock *lock = [[NSRecursiveLock alloc] init];

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    static void (^recursiveBlock)(int);
    recursiveBlock = ^(int value) {
        [lock lock];
        if (value > 0) {
            NSLog(@"value is %d",value);
            recursiveBlock(value-1);
        }
        [lock unlock];
    };
    recursiveBlock(5);
});

输出如下:

2017-12-20 15:21:09.465255+0800 Lock[82850:7057130] value is 5
2017-12-20 15:21:09.465562+0800 Lock[82850:7057130] value is 4
2017-12-20 15:21:09.465739+0800 Lock[82850:7057130] value is 3
2017-12-20 15:21:09.465906+0800 Lock[82850:7057130] value is 2
2017-12-20 15:21:09.466064+0800 Lock[82850:7057130] value is 1
1.5 dispatch_semaphore

使用方法非常简单,dispatch_semaphore_create(1)为创建信号,数字表示可以同时几个线程使用信号。为1表示同步使用。如果此处标2就和没设置信号量一样,并发自行运行。如果设置为0,则一律等待overTime时自动释放,所有代码都不执行,理论上也具有同步作用,就是慢点…

dispatch_semaphore_t signal = dispatch_semaphore_create(1);
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, 3.0f * NSEC_PER_SEC);

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    NSLog(@"线程1 等待ing");
    dispatch_semaphore_wait(signal, timeout); //signal 值 -1
    NSLog(@"线程1 sleep");
    sleep(2);
    NSLog(@"线程1");
    dispatch_semaphore_signal(signal); //signal 值 +1
    NSLog(@"线程1 发送信号");
});

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    NSLog(@"线程2 等待ing");
    dispatch_semaphore_wait(signal, timeout);
    NSLog(@"线程2 sleep");
    sleep(2);
    NSLog(@"线程2");
    dispatch_semaphore_signal(signal);
    NSLog(@"线程2 发送信号");
});

输出如下:

2017-12-20 16:28:19.286668+0800 Lock[70914:7323787] 线程2 等待ing
2017-12-20 16:28:19.286670+0800 Lock[70914:7323790] 线程1 等待ing
2017-12-20 16:28:19.286810+0800 Lock[70914:7323787] 线程2 sleep
2017-12-20 16:28:21.290357+0800 Lock[70914:7323787] 线程2
2017-12-20 16:28:21.290556+0800 Lock[70914:7323787] 线程2 发送信号
2017-12-20 16:28:21.290566+0800 Lock[70914:7323790] 线程1 sleep
2017-12-20 16:28:23.294412+0800 Lock[70914:7323790] 线程1
2017-12-20 16:28:23.294572+0800 Lock[70914:7323790] 线程1 发送信号

相关文章

  • OC--各种线程锁

    参考:正确使用多线程同步锁@synchronized()iOS中的锁iOS多线程安全详解iOS 常见知识点(三):...

  • iOS 中常见的几种锁-代码示例

    iOS 中常见的几种锁-代码示例 iOS 中常见的几种锁-代码示例

  • iOS中的常见锁

    @synchronized 日常开发中常常需要使用锁,可能大多数是使用OC封装的@synchronized,使用起...

  • iOS中的锁

    锁是一种同步机制,用于多线程环境中对资源访问的限制iOS中常见锁的性能对比图(摘自:ibireme): iOS锁的...

  • Lock

    iOS中以NS开头常见的锁的有NSCondition、NSConditionLock、NSLock、NSRecur...

  • iOS 锁

    iOS Lock(锁) 主要介绍常见的锁,以及synchronized、NSLock、递归锁、条件锁的底层分析 借...

  • iOS常见锁对象

    iOS常见锁对象: 1.互斥锁NSLock NSLock* lock = [[NSLock alloc] init...

  • iOS 笔记 - 锁

    今天简单写一下iOS中相关锁的内容,下图来自不再安全的 OSSpinLock中几种常见的锁加解锁的时间。 废弃的O...

  • iOS:常见的锁

    加锁是为了防止多条线程同时访问同一块内存,也就是为了线程同步。实现线程同步不仅仅只有加锁的方式,也可以通过 同步串...

  • iOS中的常见线程锁总结

    Created By Kunming 研究背景 我们在开发过程中,为了使应用更加高效、快速地运行,往往我们会使用到...

网友评论

      本文标题:iOS中常见的锁

      本文链接:https://www.haomeiwen.com/subject/prugwxtx.html