美文网首页iOS
iOS中的几种锁

iOS中的几种锁

作者: 无敌大闸蟹 | 来源:发表于2018-12-13 15:06 被阅读10次

    多个线程访问同一块资源的时候,很容易引发数据混乱问题 所以我们就需要给我们的任务加上锁 网上大多的例子都是卖票的

    @interface ViewController ()
    
    @property (nonatomic, assign) NSInteger count;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.count = 100;
        for (int i = 0; i < 10; i ++) {
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                for (int j = 0; j < 10; j ++) {
                    [self soldTicket];
                }
            });
        }
    }
    
    - (void)soldTicket
    {
        self.count --;
        NSLog(@"%ld",(long)self.count);
    }
    

    可以看到打印的

    image.png
    这里就是抢占了资源 当两个线程同时访问count时都为96 这里就存在数据错误和线程安全的问题了
    使用线程同步技术,按照预定的先后次序依次进行,常见的线程同步技术就是加锁

    锁分为互斥锁和自旋锁

    大概的区别就是当B线程在访问加锁的内容时线程A也来访问的话
    互斥锁:线程A会被阻塞 如果线程A运行在X处理器上的话 X会被加入等待队列 而X可以去处理其他的任务 等B访问完了之后A继续访问
    自旋锁:自旋锁一直占用CPU,他在未获得锁的情况下,一直运行,所以占用着CPU,如果不能在很短的时间内获得锁 相当耗性能

    所以对比下很容易得出结论 如果锁的任务不怎么耗时的话选择自旋锁 耗时的话选择互斥锁

    然后说几种常用的锁
    os_unfair_lock
    os_unfair_lock是自旋锁

    //初始化
    os_unfair_lock lock = OS_UNFAIR_LOCK_INIT;
    //加锁
    os_unfair_lock_lock(&lock);
    //解锁
    os_unfair_lock_unlock(&lock);
    

    需要导入#import <os/lock.h>
    代码如下

    #import "ViewController.h"
    #import <os/lock.h>
    @interface ViewController ()
    
    @property (nonatomic, assign) NSInteger count;
    
    @property (nonatomic, assign) os_unfair_lock lock;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.count = 100;
        self.lock = OS_UNFAIR_LOCK_INIT;
        for (int i = 0; i < 10; i ++) {
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                for (int j = 0; j < 10; j ++) {
                    [self soldTicket];
                }
            });
        }
    }
    
    - (void)soldTicket
    {
        os_unfair_lock_lock(&_lock);
        self.count --;
        NSLog(@"%ld",(long)self.count);
        os_unfair_lock_unlock(&_lock);
    }
    

    pthread_mutex 属于互斥锁

    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
    

    需要导入#import <pthread.h>
    初始化锁是

    pthread_mutex_init(mutex, &attr);
    

    初始化锁结束以后,销毁属性

    pthread_mutexattr_destroy(&attr)
    

    加锁解锁销毁锁

    pthread_mutex_lock(&_mutex);
    pthread_mutex_unlock(&_mutex);
    pthread_mutex_destroy(&_mutex);
    

    代码真尼玛麻烦

    #import <pthread.h>
    @interface ViewController ()
    
    @property (nonatomic, assign) NSInteger count;
    
    @property (nonatomic, assign) pthread_mutex_t lock;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.count = 100;
        pthread_mutexattr_t attr;
        pthread_mutexattr_init(&attr);
        pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT);
        pthread_mutex_init(&_lock, &attr);
        pthread_mutexattr_destroy(&attr);
        for (int i = 0; i < 10; i ++) {
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                for (int j = 0; j < 10; j ++) {
                    [self soldTicket];
                }
            });
        }
    }
    
    - (void)soldTicket
    {
        pthread_mutex_lock(&_lock);
        self.count --;
        NSLog(@"%ld",(long)self.count);
        pthread_mutex_unlock(&_lock);
        
    }
    

    NSLock是基于pthread的封装 用起来也是很方便 也是最常见的锁

    @interface ViewController ()
    
    @property (nonatomic, assign) NSInteger count;
    
    @property (nonatomic, strong) NSLock *lock;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.count = 100;
        self.lock = [[NSLock alloc] init];
        for (int i = 0; i < 10; i ++) {
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                for (int j = 0; j < 10; j ++) {
                    [self soldTicket];
                }
            });
        }
    }
    
    - (void)soldTicket
    {
        [self.lock lock];
        self.count --;
        NSLog(@"%ld",(long)self.count);
        [self.lock unlock];
        
    }
    

    NSRecursiveLockNSCondition 也是基于pthread_ mutex的封装 用法和NSLock一致 就不写了
    NSConditionLock是对NSCondition的封装 可以设定锁和解锁时候的值
    1、initWithCondition:初始化Condition,并且设置状态值
    2、lockWhenCondition:(NSInteger)condition:当状态值为condition的时候加锁
    3、unlockWithCondition:(NSInteger)condition当状态值为condition的时候解锁

    dispatch_semaphoreGCD里面的信号量 主要是三个方法
    dispatch_semaphore_create(1) 1代表最大并发量 如果信号量的值 > 0就让信号量的值减1,然后继续往下执行代码 如果信号量的值 <= 0,就会休眠等待,直到信号量的值变成>0,就让信号量的值减1,然后继续往下执行代码
    dispatch_semaphore_wait 等待
    dispatch_semaphore_signal 让信号量+1
    代码如下

    @interface ViewController ()
    
    @property (nonatomic, assign) NSInteger count;
    
    @property (nonatomic, strong) dispatch_semaphore_t semaphore;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.count = 100;
        self.semaphore = dispatch_semaphore_create(1);
        for (int i = 0; i < 10; i ++) {
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                for (int j = 0; j < 10; j ++) {
                    [self soldTicket];
                }
            });
        }
    }
    
    - (void)soldTicket
    {
        dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
        self.count --;
        NSLog(@"%ld",(long)self.count);
        dispatch_semaphore_signal(self.semaphore);
    }
    

    dispatch_queue GCD里面的 这里我们可以用串行队列的形式

    @interface ViewController ()
    
    @property (nonatomic, assign) NSInteger count;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.count = 100;
        dispatch_queue_t queue = dispatch_queue_create("sold", DISPATCH_QUEUE_SERIAL);
        for (int i = 0; i < 10; i ++) {
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                dispatch_async(queue, ^{
                    for (int j = 0; j < 10; j ++) {
                        [self soldTicket];
                    }
                });
            });
        }
    }
    
    - (void)soldTicket
    {
        self.count --;
        NSLog(@"%ld",(long)self.count);
    }
    

    @synchronized也是我们常见的锁

    @interface ViewController ()
    
    @property (nonatomic, assign) NSInteger count;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.count = 100;
        for (int i = 0; i < 10; i ++) {
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                for (int j = 0; j < 10; j ++) {
                    [self soldTicket];
                }
            });
        }
    }
    
    - (void)soldTicket
    {
        @synchronized([self class]){
            self.count --;
            NSLog(@"%ld",(long)self.count);
        }
    }
    

    dispatch_barrier_async栏栅块 这个例子好像不太适合用这个·········
    这样吧 强行栏栅块一波···

    - (void)viewDidLoad {
        [super viewDidLoad];
        self.count = 100;
        dispatch_queue_t queue = dispatch_queue_create("123", DISPATCH_QUEUE_CONCURRENT);
        for (int i = 0; i < 10; i ++) {
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                dispatch_barrier_async(queue, ^{
                    for (int j = 0; j < 10; j ++) {
                        [self soldTicket];
                    }
                });
            });
        }
    }
    
    - (void)soldTicket
    {
        self.count --;
        NSLog(@"%ld",(long)self.count);
    }
    

    后面贴上其他地方抄过来的性能对比 我也不知道真的还是假的
    锁的性能比较
    性能从高到低排序

    os_unfair_lock
    dispatch_semaphore
    pthread_mutex
    dispatch_queue(DISPATCH_QUEUE_SERIAL)
    NSLock
    NSCondition
    pthread_mutex(recursive)
    NSRecursiveLock
    NSConditionLock
    @synchronized

    相关文章

      网友评论

        本文标题:iOS中的几种锁

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