美文网首页
多线程-锁

多线程-锁

作者: Michael_涵 | 来源:发表于2019-04-01 17:36 被阅读0次

    Quick Start Guide

    1. @synchronized
    2. NSLock 对象锁
    3. NSRecursiveLock 递归锁
    4. NSConditionLock 条件锁
    5. pthread_mutex 互斥锁
    6. dispatch_semaphore 信号量锁
    7. OSSpinLock

    性能对比

    这里只能反应单线程情况,不能反映多线程下的实际性能

    2208956-4a024a1c6c6214db.png

    Getting Started

    1. @synchronized

    @synchronized(obj) {
      //这里obj指oc对象,一般为self
    }
    

    注意:加锁的代码量要少,oc对象在多个线程都是同一个对象

    2. NSLock

    //创建锁
    NSLock *lock = [[NSLock alloc] init];
    ...
    [lock lock];
    //逻辑处理
    [lock unlock];
    

    注意:lock不能多次调用,会造成死锁

    3. NSRecursiveLock

    //死锁-递归
    NSLock *lock = [[NSLock alloc] init];
    dispatch_async(self.queue, ^{
      static void (^method)(int value);
      method = ^(int number) {
          [lock lock];
          //条件
          method(number)
          [lock unlock];
      };
      method(10);
    });
    
    //正确使用-递归
    NSLock *lock = [[NSRecursiveLock alloc] init];
    __block int num = 10;
    dispatch_async(self.queue, ^{
      static void (^method)(int value);
      method = ^(int number) {
          [lock lock];
          //条件
          method(--number)
          [lock unlock];
      };
      method(num);
    });
    

    NSRecursiveLock在递归或者循环内(同一线程)使用不会造成死锁

    4. NSConditionLock

    NSConditionLock *lock = [[NSConditionLock alloc] init];
    
    //线程1
    dispatch_async(self.queue, ^{
      for (int i=0;i<10;i++) {
        [lock lock];
        NSLog(@"%d",i);
        [lock unlockWithCondition:5];
      }
    });
    //线程2
    dispatch_async(self.queue, ^{
      [lock lockWhenCondition:5];
      [lock unlock];
    });
    

    5. pthread_mutex

    //引用
    #include <pthread.h>
    
    //通过设置attr类型可以设置递归锁,互斥锁等
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL)
    
    __block pthread_mutex_t mutex;
    pthread_mutex_init(&mutex,&attr);
    
    dispatch_async(self.queue, ^{
      pthread_mutex_lock(&mutex);
      NSLog(@"thread 1");
      pthread_mutex_unlock(&mutex);
    });
    
    dispatch_async(self.queue, ^{
      pthread_mutex_lock(&mutex);
      NSLog(@"thread 2");
      pthread_mutex_unlock(&mutex);
    });
    

    此方法比较基础,如NSLock,NSConditionLock,,NSRecursiveLock底层实现都是用此方法实现

    6. dispatch_semaphore

    //创建信号量,并设置初始信号总量
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
    dispatch_queue_t queue = dispatch_queue_create("testqueue", DISPATCH_QUEUE_SERIAL);
    
    dispatch_async(queue, ^{
       //模拟耗时操作
       [NSThread sleepForTimeInterval:2];
      //使总信号量减1,当信号总量为0时会一直等待,否则正常执行
      dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
      NSLog(@"thread 1");
      //发送一个信号,让信号总量加1
      dispatch_semaphore_signal(semaphore);
    });
    
    dispatch_async(queue, ^{
      dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
      NSLog(@"thread 2");
      dispatch_semaphore_signal(semaphore);
    });
    

    7. OSSpinLock

    //创建锁
    lock = OS_SPINLOCK_INIT;
    ...
    //加锁
    OSSpinLockLock(&lock);
    ...
    //解锁
    OSSpinLockUnlock(&lock);
    

    不推荐使用,如果一个低优先级的线程获得锁并访问共享资源,这时一个高优先级的线程也尝试获得这个锁,它会处于 spin lock 的忙等状态从而占用大量 CPU。此时低优先级线程无法与高优先级线程争夺 CPU 时间,从而导致任务迟迟完不成、无法释放 lock。这并不只是理论上的问题,libobjc 已经遇到了很多次这个问题了,于是苹果的工程师停用了 OSSpinLock。ios 10以后可以使用os_unfair_lock代替OSSpinLock

    相关文章

      网友评论

          本文标题:多线程-锁

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