美文网首页OC基础原理
iOS锁系列-NSLock对象锁

iOS锁系列-NSLock对象锁

作者: lltree | 来源:发表于2018-04-16 17:07 被阅读254次

原文,本文只为学习

对象锁:代码为[临界区:共同访问一段代码]synchronized(Object)语句指定的对象进行加锁

示例:

//主线程中
    NSLock *lock = [[NSLock alloc] init];
    
    //线程1
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [lock lock];
        NSLog(@"线程1");
        sleep(2);
        [lock unlock];
        NSLog(@"线程1解锁成功");
    });

    //线程2
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        sleep(1);//以保证让线程2的代码后执行
        [lock lock];
        NSLog(@"线程2");
        [lock unlock];
    });

2016-08-19 14:23:09.659 ThreadLockControlDemo[1754:129663] 线程1
2016-08-19 14:23:11.663 ThreadLockControlDemo[1754:129663] 线程1解锁成功
2016-08-19 14:23:11.665 ThreadLockControlDemo[1754:129659] 线程2

NSLock的执行原理:
线程 1 中的 lock 锁上了,所以线程 2 中的 lock 加锁失败,阻塞线程 2,但 2 s 后线程 1 中的 lock 解锁,线程 2 就立即加锁成功,执行线程 2 中的后续代码。

查到的资料显示互斥锁会使得线程阻塞,阻塞的过程又分两个阶段,第一阶段是会先空转,可以理解成跑一个 while 循环,不断地去申请加锁,在空转一定时间之后,线程会进入 waiting 状态,此时线程就不占用CPU资源了,等锁可用的时候,这个线程会立即被唤醒。

所以如果将上面线程 1 中的 sleep(2); 改成 sleep(10); 输出的结果会变成

2016-08-19 14:25:16.226 ThreadLockControlDemo[1773:131824] 线程1
2016-08-19 14:25:26.231 ThreadLockControlDemo[1773:131831] 线程2
2016-08-19 14:25:26.231 ThreadLockControlDemo[1773:131824] 线程1解锁成功

从上面的两个输出结果可以看出,线程 2 lock 的第一秒,是一直在轮询请求加锁的,因为轮询有时间间隔,所以 ”线程 2“ 的输出晚于 ”线程 1 解锁成功“,但线程 2 lock 的第九秒,是当锁可用的时候,立即被唤醒,所以 ”线程 2“ 的输出早于 ”线程 1 解锁成功“。多做了几次试验,发现轮询 1 秒之后,线程会进入 waiting 状态。

//主线程中
    NSLock *lock = [[NSLock alloc] init];
    
    //线程1
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [lock lock];
        NSLog(@"线程1");
        sleep(10);
        [lock unlock];
    });
    
    //线程2
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        sleep(1);//以保证让线程2的代码后执行
        if ([lock tryLock]) { //尝试加锁
            NSLog(@"线程2");
            [lock unlock];
        } else {
            NSLog(@"尝试加锁失败");
        }
    });

2016-08-19 11:42:54.433 ThreadLockControlDemo[1256:56857] 线程1
2016-08-19 11:42:55.434 ThreadLockControlDemo[1256:56861] 尝试加锁失败

由上面的结果可得知,tryLock 并不会阻塞线程。[lock tryLock] 能加锁返回 YES,不能加锁返回 NO,然后都会执行后续代码。

如果将 [lock tryLock] 替换成

[lock lockBeforeDate:[NSDate dateWithTimeIntervalSinceNow:10]

的话,则会返回 YES,输出 “线程 2“,lockBeforeDate: 方法会在所指定 Date 之前尝试加锁,会阻塞线程,如果在指定时间之前都不能加锁,则返回 NO,指定时间之前能加锁,则返回 YES。

@protocol NSLocking

- (void)lock;//加锁
- (void)unlock;//解锁

@end

@interface NSLock : NSObject <NSLocking> {
@private
    void *_priv;
}

//尝试加锁,不会阻塞线程。true则加锁成功,false则失败,说明其他线程在加锁中这个方法无论如何都会立即返回。
- (BOOL)tryLock;

//尝试在指定NSDate之前加锁,会阻塞线程。true则加锁成功,false则失败,说明其他线程在加锁中这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待。
- (BOOL)lockBeforeDate:(NSDate *)limit;

//name 是用来标识用的
@property (nullable, copy) NSString *name API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));

@end

相关文章

  • iOS锁系列-目录

    1、 iOS锁系列-NSLock对象锁2、iOS锁系列-NSConditionLock条件锁3、iOS锁系列-NS...

  • iOS常见锁对象

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

  • iOS锁系列-NSLock对象锁

    原文,本文只为学习 对象锁:代码为[临界区:共同访问一段代码]synchronized(Object)语句指定的对...

  • iOS开发中常用的锁

    锁是线程编程同步工具的基础,在iOS开发中常用的锁有以下几种: @synchronized NSLock 对象锁 ...

  • iOS 锁

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

  • 线程锁

    iOS中有几种线程锁:@synchronized、NSLock以及NSRecursiveLock(递归锁)。本文用...

  • 互斥锁 自旋锁 递归锁 条件锁 读写锁 互斥锁:pthread_ mutex_t(NSLock基于此封装)每个对象...

  • iOS都有哪些锁

    iOS都有哪些锁:synchronized 、atomic、oSSpinLook、NSLock、dispatch_...

  • iOS锁-NSLock

    NSLock 下面是苹果官方文档的说法: An object that coordinates the opera...

  • iOS -锁-NSLock

    NSLock是iOS开发中最基础的锁。它继承自NSObject,遵守NSLocking协议。用于处理线程安全问题。...

网友评论

    本文标题:iOS锁系列-NSLock对象锁

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