其他分享
首页 > 其他分享> > IOS 关于锁

IOS 关于锁

作者:互联网

前言

为什么需要锁:
多条线程存在同时操作(删、查、读、写)同一个文件or对象or变量。如果不是同时或者不是同一个那就不用加锁了。关键变量:必须是“同时”,“同一事物”

自旋锁OSSpinLock

///  自旋锁 需要导入头文件:#import <libkern/OSAtomic.h>
- (void)testSpinLock {
    __block OSSpinLock oslock = OS_SPINLOCK_INIT;
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"%@",[NSThread currentThread]);
        NSLog(@"1准备上锁");
        OSSpinLockLock(&oslock);
        int time = arc4random() %5;
        NSLog(@"1线程:%d",time);
        sleep(time);
        OSSpinLockUnlock(&oslock);
        NSLog(@"1解锁");
    });
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"%@",[NSThread currentThread]);
        NSLog(@"2准备上锁");
        OSSpinLockLock(&oslock);
        int time = arc4random() %5;
        NSLog(@"2线程:%d",time);
        sleep(time);
        OSSpinLockUnlock(&oslock);
        NSLog(@"2解锁");
    });
}

不公平锁os_unfair_lock

/// 不公平锁:#import <os/lock.h>
- (void)testUnfailLock {
    static os_unfair_lock lock = OS_UNFAIR_LOCK_INIT;
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"1准备上锁");
        os_unfair_lock_lock(&lock);
        int time = arc4random() %5;
        NSLog(@"1线程:%d",time);
        sleep(time);
        os_unfair_lock_unlock(&lock);
        NSLog(@"1解锁");
    });
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"2准备上锁");
        os_unfair_lock_lock(&lock);
        int time = arc4random() %5;
        NSLog(@"2线程:%d",time);
        sleep(time);
        os_unfair_lock_unlock(&lock);
        NSLog(@"2解锁");
    });
}

互斥锁

pthread_mutex_t

/// 互斥锁 #import <pthread.h>
- (void)testMutexLock {
    static pthread_mutex_t mutex_t;
    pthread_mutex_init(&mutex_t,NULL);
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"1准备上锁");
        pthread_mutex_lock(&mutex_t);
        int time = arc4random() %5;
        NSLog(@"1线程:%d",time);
        sleep(time);
        pthread_mutex_unlock(&mutex_t);
        NSLog(@"1解锁");
    });
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"2准备上锁");
        pthread_mutex_lock(&mutex_t);
        int time = arc4random() %5;
        NSLog(@"2线程:%d",time);
        sleep(time);
        pthread_mutex_unlock(&mutex_t);
        NSLog(@"2解锁");
    });
//    pthread_mutex_destroy(&recursiveMutex)
}

NSLock

- (id) init
 {
   if (nil != (self = [super init]))
   {
       if (0 != pthread_mutex_init(&_mutex, &attr_reporting))
        {
          DESTROY(self);
         }
    }
   return self;
 }

 - (BOOL) lockBeforeDate: (NSDate*)limit
 {
   do{
       int err = pthread_mutex_trylock(&_mutex);
       if (0 == err)
             {
           CHK(Hold)
               return YES;
             }
       if (EDEADLK == err)
             {
               (*_NSLock_error_handler)(self, _cmd, NO, @"deadlock");
             }
       sched_yield();
     } while ([limit timeIntervalSinceNow] > 0);
   return NO;
 }
- (void)testNSLock {
    NSLock *lock = [NSLock new];
    //线程1
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"1准备上锁");
        [lock lock];
        int time = arc4random() %5;
        NSLog(@"1线程:%d",time);
        sleep(time);
        [lock unlock];
        NSLog(@"1解锁");
    });

    //线程2
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"1准备上锁");
        // 尝试上锁,获取资源,如果获取不超过,释放自由,在给定的时间内,一直轮询获取锁,
        BOOL ret =  [lock lockBeforeDate:[NSDate dateWithTimeIntervalSinceNow:4]];
        if (ret) {
            int time = arc4random() %5;
            NSLog(@"1线程:%d",time);
            [lock unlock];
        }else{
            NSLog(@"失败");
        }
    });
}

递归锁

MutexRecursive

/// 递归锁 MutexRecursive
- (void)testMutexRecursive {
    static pthread_mutex_t mutex_t;
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
    pthread_mutex_init(&mutex_t, &attr);
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        
        static void (^OneBlock)(int);
        OneBlock = ^(int value) {
            NSLog(@"%d准备上锁",value);
            pthread_mutex_lock(&mutex_t);
            int time = arc4random() %5;
            NSLog(@"%d线程:%d",value,time);
            if(value > 0){
                OneBlock(value - 1);
            }
            sleep(time);
            pthread_mutex_unlock(&mutex_t);
            NSLog(@"%d解锁",value);
        };
        OneBlock(5);
        NSLog(@"执行完成");
        
    });
    
//    pthread_mutex_destroy(&recursiveMutex)
}

NSRecursiveLock

- (void)testNSRecursiveLock {
    NSRecursiveLock *recursiveLock = [NSRecursiveLock new];
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        
        static void (^OneBlock)(int);
        OneBlock = ^(int value) {
            NSLog(@"%d准备上锁",value);
            [recursiveLock lock];
            int time = arc4random() %5;
            NSLog(@"%d线程:%d",value,time);
            if(value > 0){
                OneBlock(value - 1);
            }
            sleep(time);
            [recursiveLock unlock];
            NSLog(@"%d解锁",value);
        };
        OneBlock(5);
        NSLog(@"执行完成");
        
    });
}

条件锁

pthread_cond

- (void)testMutexCond {
    static pthread_mutex_t mutex_t;
    static pthread_cond_t cond_t;
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
    pthread_mutex_init(&mutex_t, &attr);
    
    pthread_cond_init(&cond_t,NULL);
    
    //线程1
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"1准备上锁");
        pthread_mutex_lock(&mutex_t);
        pthread_cond_wait(&cond_t, &mutex_t);
        int time = arc4random() %5;
        NSLog(@"1线程:%d",time);
        sleep(time);
        pthread_mutex_unlock(&mutex_t);
        NSLog(@"1解锁");
    });
    //线程1
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"2准备上锁");
        pthread_mutex_lock(&mutex_t);
        
        struct timespec outtime;
        outtime.tv_sec = time(NULL) + 5;
        outtime.tv_nsec = 0;

        pthread_cond_timedwait(&cond_t, &mutex_t, &outtime);
        int time = arc4random() %5;
        NSLog(@"2线程:%d",time);
        sleep(time);
        pthread_mutex_unlock(&mutex_t);
        NSLog(@"2解锁");
    });
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"发送了一个信号");
        pthread_cond_signal(&cond_t);
        // 广播一个信号
//        pthread_cond_broadcast(&cond_t);
    });
//    pthread_mutex_destroy(&mutex_t);
//    pthread_cond_destroy(&cond);
//    pthread_mutexattr_destroy(&attr);
}

NSCondition

- (void)testCondition {
    NSCondition *condition = [NSCondition new];
    
    //线程1
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"1准备上锁");
        [condition lock];
        int time = arc4random() %5;
        NSLog(@"1线程:%d",time);
        sleep(time);
        [condition unlock];
        NSLog(@"1解锁");
    });
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"2准备上锁");
        [condition lock];
        NSLog(@"2成功上锁,进入等待");
        if ([condition waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:20]]) {// 等一个信号,或者超时, 如果这个线程还使用了lock 需要放在lock 之后
            NSLog(@"2收到了信号");
        }else {
            NSLog(@"2超时");
        }
        
        int time = arc4random() %5;
        NSLog(@"2线程:%d",time);
        sleep(time);
        [condition unlock];
        NSLog(@"2解锁");
    });
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"3准备上锁");
        [condition lock];
        NSLog(@"3成功上锁,进入等待");
        [condition wait];// 不设置超时 一直等待知道收到信号
        int time = arc4random() %5;
        NSLog(@"3线程:%d",time);
        sleep(time);
        [condition unlock];
        NSLog(@"3解锁");
    });
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"4准备上锁");
        [condition lock];
        NSLog(@"4成功上锁");
        int time = arc4random() %5;
        NSLog(@"4线程:%d",time);
        sleep(time);
        [condition unlock];
        NSLog(@"4解锁");
    });
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"5准备上锁");
        [condition lock];
        NSLog(@"5成功上锁,进入等待");
        if ([condition waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:50]]) {// 等一个信号,或者超时, 如果这个线程还使用了lock 需要放在lock 之后
            NSLog(@"5收到了信号");
        }else {
            NSLog(@"5超时");
        }
        
        int time = arc4random() %5;
        NSLog(@"5线程:%d",time);
        sleep(time);
        [condition unlock];
        NSLog(@"5解锁");
    });
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"发送了一个信号");
//        [condition signal];
        // 或者广播一个信号,
        [condition broadcast];
    });
}

NSConditionLock

- (void)testNSConditionLock {
    NSConditionLock *oneLock = [[NSConditionLock alloc] initWithCondition:0];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"1准备上锁");
        [oneLock lock];
        NSLog(@"1成功上锁");
        
        int time = arc4random() %5;
        NSLog(@"1线程:%d",time);
        sleep(time);
        [oneLock unlock];
        NSLog(@"1解锁");
    });
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"2准备上锁");
        [oneLock lockWhenCondition:0];
        NSLog(@"2成功上锁");
        
        int time = arc4random() %5;
        NSLog(@"2线程:%d",time);
        sleep(time);
        [oneLock unlockWithCondition:3];
        NSLog(@"2解锁");
    });
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"3准备上锁");
        [oneLock lockWhenCondition:3];
        NSLog(@"3成功上锁");
        
        int time = arc4random() %5;
        NSLog(@"3线程:%d",time);
        sleep(time);
        [oneLock unlockWithCondition:4];
        NSLog(@"3解锁");
    });
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"4准备上锁");
        [oneLock lockWhenCondition:4];
        NSLog(@"4成功上锁");
        
        int time = arc4random() %5;
        NSLog(@"4线程:%d",time);
        sleep(time);
        [oneLock unlockWithCondition:5];
        NSLog(@"4解锁");
    });
}

读写锁

- (void)testrwLock {
    static pthread_rwlock_t rwlock_t;
    pthread_rwlock_init(&rwlock_t, nil);
    for (int i = 0; i< 10; i++) {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            NSLog(@"%dread ready",i);
            pthread_rwlock_rdlock(&rwlock_t);
            int time = arc4random() %5;
            NSLog(@"%dreading:%d",i,time);
            sleep(time);
            NSLog(@"%dreaded",i);
            pthread_rwlock_unlock(&rwlock_t);
        });
    }
    for (int i = 10; i< 20; i++) {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            NSLog(@"%dwrite ready",i);
            pthread_rwlock_wrlock(&rwlock_t);
            int time = arc4random() %5;
            NSLog(@"%dwriting:%d",i,time);
            sleep(time);
            NSLog(@"%dwriteded",i);
            pthread_rwlock_unlock(&rwlock_t);
        });
    }
    for (int i = 20; i< 30; i++) {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            NSLog(@"%dread ready",i);
            pthread_rwlock_rdlock(&rwlock_t);
            int time = arc4random() %5;
            NSLog(@"%dreading:%d",i,time);
            sleep(time);
            NSLog(@"%dreaded",i);
            pthread_rwlock_unlock(&rwlock_t);
        });
    }
}

synchronized

- (void)testsynchronized {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"1准备上锁");
        @synchronized (self) {
            NSLog(@"1成功上锁");
            
            int time = arc4random() %5;
            NSLog(@"1线程:%d",time);
            sleep(time);
        }
        NSLog(@"1解锁");
    });
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"2准备上锁");
        @synchronized (self) {
            NSLog(@"2成功上锁");
            
            int time = arc4random() %5;
            NSLog(@"2线程:%d",time);
            sleep(time);
        }
        NSLog(@"2解锁");
    });
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"3准备上锁");
        @synchronized (self) {
            NSLog(@"3成功上锁");
            
            int time = arc4random() %5;
            NSLog(@"3线程:%d",time);
            sleep(time);
        }
        NSLog(@"3解锁");
    });
}

信号量

- (void)testSemphore{
    dispatch_semaphore_t semp = dispatch_semaphore_create(1); //传入值必须 >=0, 若传入为0则阻塞线程并等待timeout,时间到后会执行其后的语句
    dispatch_time_t overTime = dispatch_time(DISPATCH_TIME_NOW, 5.0f * NSEC_PER_SEC);

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"1准备上锁");
        dispatch_semaphore_wait(semp, overTime);// 如果signal > 0 则-1 继续向下执行,如果signal == 0 则等待
        int time = arc4random() %5;
        NSLog(@"1线程:%d",time);
        sleep(time);
        dispatch_semaphore_signal(semp); // singal +1
        NSLog(@"1解锁");
    });
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"2准备上锁");
        dispatch_semaphore_wait(semp, overTime);
        int time = arc4random() %5;
        NSLog(@"2线程:%d",time);
        sleep(time);
        dispatch_semaphore_signal(semp);
        NSLog(@"2解锁");
    });
}

总结:

标签:IOS,pthread,NSLog,dispatch,线程,关于,time,mutex
来源: https://blog.csdn.net/wutao63/article/details/122428961