谈谈iOS中的几种锁

2020-01-18 17:03:32于丽

 

这里就不在详细介绍了,感兴趣的大家可以自己查阅相关资料。

第三部分:锁的作用

这个比较通俗来讲:就是为了防止在多线程(多任务)的情况下对共享资源(临界资源)的脏读或者脏写。也可以理解为:执行多线程时用于强行限制资源访问的同步机制,即并发控制中保证互斥的要求。

第四部分:iOS中锁的实现

先看看iOS中NSLock类的.h文件。这里就不在写上来了。从代码中可以看出,该类分成了几个子类:NSLock、NSConditionLock、NSRecursiveLock以及NSCondition。然后有一个NSLocking的协议:


@protocol NSLocking
- (void)lock;
- (void)unlock;
@end

这几个子类都遵循了NSLock的协议,这里简单介绍一下其中的几个方法:

对于tryLock方法,尝试获取一个锁,并且立刻返回Bool值,YES表示获取了锁,NO表示没有获取锁失败。 lockBeforeDate:方法,在某个时刻之前获取锁,如果获取成功,则返回YES,NO表示获取锁失败。接下来就让我们看一下iOS中实现锁的方式:

方式1 使用NSLock类


- (void)nslockDemo {
  NSLock *myLock = [[NSLock alloc] init];
  _testLock = [[TestLock alloc] init];
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [myLock lock];
    [_testLock method1];
    sleep(5);
    [myLock unlock];
    if ([myLock tryLock]) {
      NSLog(@"可以获得锁");
    }else {
      NSLog(@"不可以获得所");
    }
  });
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    sleep(1);
    if ([myLock tryLock]) {
      NSLog(@"---可以获得锁");
    }else {
      NSLog(@"----不可以获得所");
    }
    [myLock lock];
    [_testLock method2];
    [myLock unlock];
  });
}

方式2 使用@synchorize


- (void)synchronizeDemo {
  _testLock = [[TestLock alloc] init];
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    @synchronized (_testLock) {
      [_testLock method1];
      sleep(5);
    }
  });
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    sleep(1);
    @synchronized (_testLock) {
      
      [_testLock method2];
    }
  });
}

对于synchorize指令中使用的testLock为该锁标示,只有标示相同的时候才满足锁的效果。它的优点是不用显式地创建锁,便可以实现锁的机制。但是它会隐式地添加异常处理程序来保护代码,该程序在抛出异常的时候自动释放锁。

方式3 使用gcd


- (void)gcdDemo {
  _testLock = [[TestLock alloc] init];
  dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    [_testLock method1];
    sleep(5);
    dispatch_semaphore_signal(semaphore);
  });
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    sleep(1);
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    [_testLock method2];
    dispatch_semaphore_signal(semaphore);
  });

}