美文网首页
iOS开发过程中的各种锁

iOS开发过程中的各种锁

作者: SDBridge | 来源:发表于2017-04-02 11:16 被阅读52次

    各种锁的效率图

    iOS锁的效率.png
    //
    //  ViewController.m
    //  LockKata1
    //
    //  Created by Code_Hou on 2017/4/2.
    //  Copyright © 2017年 侯森魁. All rights reserved.
    //
    
    #import "ViewController.h"
    #import <libkern/OSAtomic.h>
    #import <pthread.h>
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    #pragma mark--自旋锁
    /*
     void OSSpinLockh_hsk(){
     
             __block OSSpinLock oslosk  =OS_SPINLOCK_INIT;
     
      
             dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
             
                     NSLog(@"线程1 准备上锁 当前线程 ");
                     
                     OSSpinLockLock(&oslosk);
                     sleep(4);
                     NSLog(@"线程1");
                     OSSpinLockUnlock(&oslosk);
                     NSLog(@"线程1 解锁成功");
                     NSLog(@"-----------------------------");
             
             
             
             });
             dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                     NSLog(@"线程2 准备上锁");
                     OSSpinLockLock(&oslosk);
                     NSLog(@"线程2");
                     OSSpinLockUnlock(&oslosk);
                     NSLog(@"线程2 解锁成功");
             });
     
     }
     */
    /*
     控制台:
     
     function:__OSSpinLockh_hsk_block_invoke line:26 content:线程1 准备上锁 当前线程  🙃Multi Threaded
     
     function:__OSSpinLockh_hsk_block_invoke.16 line:39 content:线程2 准备上锁 🙃Multi Threaded
     
     function:__OSSpinLockh_hsk_block_invoke line:30 content:线程1 🙃Multi Threaded
     
     function:__OSSpinLockh_hsk_block_invoke line:32 content:线程1 解锁成功 🙃Multi Threaded
     
     function:__OSSpinLockh_hsk_block_invoke line:33 content:----------------------------- 🙃Multi Threaded
     
     function:__OSSpinLockh_hsk_block_invoke.16 line:41 content:线程2 🙃Multi Threaded
     
     function:__OSSpinLockh_hsk_block_invoke.16 line:43 content:线程2 解锁成功 🙃Multi Threaded
    
     */
    
    #pragma mark----信号量
    void dispatch_semaphore(){
        dispatch_semaphore_t signal =dispatch_semaphore_create(0);//传入值必须>=0,若传入为0则阻塞线程并等待tiomout,时间到后会执行其后的语句
        dispatch_time_t overTime  =dispatch_time(DISPATCH_TIME_NOW, 3.0f*NSEC_PER_SEC);
        
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
          
            NSLog(@"线程1 等待ing");
            dispatch_semaphore_wait(signal, overTime);//signal 值 -1
            
            NSLog(@"线程1");
            dispatch_semaphore_signal(signal);//signal 值+1
            NSLog(@"线程1 发送信号");
        });
        
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            NSLog(@"线程2 等待ing");
            dispatch_semaphore_wait(signal, overTime);
            NSLog(@"线程2");
            dispatch_semaphore_signal(signal);
            NSLog(@"线程2 发送信号");
        
        });
        
        /*
         传入1  overTime 不会生效
         dispatch_semaphore_t signal =dispatch_semaphore_create(1);
         控制台:
         某一次:
         2017-04-02 09:02:26.193 LockKata1[1336:38092] 线程1 等待ing
         2017-04-02 09:02:26.194 LockKata1[1336:38092] 线程1
         2017-04-02 09:02:26.193 LockKata1[1336:38096] 线程2 等待ing
         2017-04-02 09:02:26.194 LockKata1[1336:38092] 线程1 发送信号
         2017-04-02 09:02:26.194 LockKata1[1336:38096] 线程2
         2017-04-02 09:02:26.195 LockKata1[1336:38096] 线程2 发送信号
         
         某一次:
         2017-04-02 09:03:11.098 LockKata1[1353:38732] 线程1 等待ing
         2017-04-02 09:03:11.098 LockKata1[1353:38735] 线程2 等待ing
         2017-04-02 09:03:11.098 LockKata1[1353:38732] 线程1
         2017-04-02 09:03:11.100 LockKata1[1353:38732] 线程1 发送信号
         2017-04-02 09:03:11.100 LockKata1[1353:38735] 线程2
         2017-04-02 09:03:11.101 LockKata1[1353:38735] 线程2 发送信号
         
         传入0  overTime 生效
         dispatch_semaphore_t signal =dispatch_semaphore_create(0)
         
         控制台:
         2017-04-02 09:06:53.872 LockKata1[1376:41653] 线程1 等待ing
         2017-04-02 09:06:53.872 LockKata1[1376:41638] 线程2 等待ing
         2017-04-02 09:06:56.946 LockKata1[1376:41653] 线程1
         2017-04-02 09:06:56.946 LockKata1[1376:41638] 线程2
         2017-04-02 09:06:56.946 LockKata1[1376:41638] 线程2 发送信号
         2017-04-02 09:06:56.946 LockKata1[1376:41653] 线程1 发送信号
         
         */
        
    }
    
    #pragma mark--互斥锁
    void pthread_mutex_hsk(){
        
          pthread_mutex_t  pLock = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
    //    pthread_mutex_t_init(&pLock,NULL);
        
        //线程1
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            
            //子线程网络请求
            NSLog(@"线程1 准备上锁");
            pthread_mutex_lock(&pLock);
            sleep(3);
            NSLog(@"线程1");
            pthread_mutex_unlock(&pLock);
        
        });
        //线程2
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            
            //子线程网络请求
            NSLog(@"线程2    准备上锁");
            pthread_mutex_lock(&pLock);
            NSLog(@"线程2");
            pthread_mutex_unlock(&pLock);
        
        });
        /*
         lock 和unlock 成对出现
         
         */
        /*
         控制台日志:
         2017-04-02 09:33:21.575 LockKata1[1493:57547] 线程2    准备上锁
         2017-04-02 09:33:21.575 LockKata1[1493:57545] 线程1 准备上锁
         2017-04-02 09:33:21.576 LockKata1[1493:57547] 线程2
         2017-04-02 09:33:24.646 LockKata1[1493:57545] 线程1
    
         
         */
        
    
    
        
    }
    #pragma mark---递归锁
    void pthread_mutex_recursive(){
        static pthread_mutex_t pLock;
        
        pthread_mutexattr_t attr;
        
        pthread_mutexattr_init(&attr);//初始化attr并且给它赋予默认值
        pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);//设置锁类型,这里设置为递归锁
        pthread_mutex_init(&pLock, &attr);
        pthread_mutexattr_destroy(&attr);//销毁一个属性对象,在重新进行初始化之前改结构不能重新使用
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            
            static void (^RecursiveBlock)(int);
            
            RecursiveBlock = ^(int value){
                pthread_mutex_lock(&pLock);
                if (value > 0) {
                    
                    NSLog(@"value:%d",value);
                    RecursiveBlock(value-1);
                }
                pthread_mutex_unlock(&pLock);
            
            };
            RecursiveBlock(5);
            
        });
        /*
         上面的代码如果我们用 pthread_mutex_init(&pLock, NULL) 初始化会出现死锁的情况,递归锁能很好的避免这种情况的死锁;
    
         */
        /*
         控制台日志:
         
         2017-04-02 09:58:24.701 LockKata1[1591:70699] value:5
         2017-04-02 09:58:24.701 LockKata1[1591:70699] value:4
         2017-04-02 09:58:24.703 LockKata1[1591:70699] value:3
         2017-04-02 09:58:24.704 LockKata1[1591:70699] value:2
         2017-04-02 09:58:24.705 LockKata1[1591:70699] value:1
         */
    
        
    }
    #pragma mark---NSLock
    void NSLock_hsk(){
        NSLock *lock = [NSLock new];
        //线程1
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            
            NSLog(@"线程1 尝试加锁ing...");
            [lock lock];
            sleep(3);//睡眠3秒
            NSLog(@"线程1");
            [lock unlock];
            NSLog(@"线程1解锁成功");
            
        });
        //线程2
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            NSLog(@"线程2 尝试加锁ing...");
            
            BOOL x = [lock lockBeforeDate:[NSDate dateWithTimeIntervalSinceNow:6]];
            
            if (x) {
                NSLog(@"线程2");
                [lock unlock];
            }else{
                NSLog(@"失败");
            }
        });
    
        /*
         
         2017-04-02 10:10:25.265 LockKata1[1663:78655] 线程1 尝试加锁ing...
         2017-04-02 10:10:25.265 LockKata1[1663:78654] 线程2 尝试加锁ing...
         2017-04-02 10:10:28.334 LockKata1[1663:78655] 线程1
         2017-04-02 10:10:28.334 LockKata1[1663:78654] 线程2
         2017-04-02 10:10:28.334 LockKata1[1663:78655] 线程1解锁成功
    
         */
        
    }
    #pragma mark---NSCondition
    void NSCondition_hsk(){
        
    
        NSCondition *cLock = [NSCondition new];
        //线程1
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            NSLog(@"start");
            [cLock lock];
            [cLock waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]];
            //等待2 秒
            NSLog(@"线程1");
            
            [cLock unlock];
            
        });
        /*
         
         */
        /*
         2017-04-02 10:16:21.217 LockKata1[1709:82528] start
         2017-04-02 10:16:23.287 LockKata1[1709:82528] 线程1
         */
        
        
    }
    void NSCondition_hsk1(){
      
        NSCondition *cLock =[NSCondition new];
        
        //线程1
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            
            [cLock lock];
            NSLog(@"线程1加锁成功");
            [cLock wait];
            NSLog(@"线程1");
            [cLock unlock];
         });
        
        //线程2
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            
            [cLock lock];
            NSLog(@"线程2加锁成功");
            [cLock wait];
            NSLog(@"线程2");
            [cLock unlock];
        });
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            
            sleep(2);
            NSLog(@"唤醒一个等待的线程");
            
            [cLock broadcast];
            
        });
        /*
         [cLock signal]
         
         控制台日志:
         2017-04-02 10:26:38.063 LockKata1[1751:87871] 线程1加锁成功
         2017-04-02 10:26:38.064 LockKata1[1751:87872] 线程2加锁成功
         2017-04-02 10:26:40.134 LockKata1[1751:87874] 唤醒一个等待的线程
         2017-04-02 10:26:40.135 LockKata1[1751:87871] 线程1
         
         [cLock broadcast];
         控制台日志:
         2017-04-02 10:36:34.442 LockKata1[1782:91902] 线程1加锁成功
         2017-04-02 10:36:34.443 LockKata1[1782:91900] 线程2加锁成功
         2017-04-02 10:36:36.504 LockKata1[1782:91899] 唤醒一个等待的线程
         2017-04-02 10:36:36.505 LockKata1[1782:91902] 线程1
         2017-04-02 10:36:36.506 LockKata1[1782:91900] 线程2
         
         */
    }
    #pragma mark--经典错误例子
    //我在这里写的C方法 在AppDelegate.m方法中一样能调用,(*@ο@*) 哇~,夸类了,还是 C语言好
    void errorUseWithNSLock(){
        
        NSLock *rLock = [NSLock new];
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            
            static void(^RecursiveBlock)(int);
            
            RecursiveBlock = ^(int value){
            
                [rLock lock];
                
                if (value>0) {
                    NSLog(@"线程%d",value);
                    
                    RecursiveBlock(value - 1);
                }
                [rLock unlock];
                
            };
            RecursiveBlock(4);
            
        });
        /*
         这是一段典型的死锁情况。在我们的线程中,RecursiveMethod是递归调用的。所以每次进入这个block时,都会去加一次锁,而从第二次开始,由于锁已经被使用了且没有解锁,所以它需要等待锁被解除,这样就导致了死锁,线程被阻塞住了。
         控制台日志:
         2017-04-02 10:47:37.882 LockKata1[1823:97654] 线程4
         2017-04-02 10:47:37.883 LockKata1[1823:97654] *** -[NSLock lock]: deadlock (<NSLock: 0x7b858f80> '(null)')
         2017-04-02 10:47:37.884 LockKata1[1823:97654] *** Break on _NSLockError() to debug.
    
         */
    }
    
    void NSRecursiveLock_hsk(){
        
        NSRecursiveLock *rLock =[NSRecursiveLock new];
        
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            static void(^RecursiveBlock)(int);
            RecursiveBlock = ^(int value){
                [rLock lock];
                if (value>0) {
                    NSLog(@"线程%d",value);
                    RecursiveBlock(value-1);
                }
                [rLock unlock];
            
            
            };
            RecursiveBlock(5);
        });
        /*
         控制台:
         2017-04-02 10:55:48.718 LockKata1[1855:100893] 线程5
         2017-04-02 10:55:48.718 LockKata1[1855:100893] 线程4
         2017-04-02 10:55:48.719 LockKata1[1855:100893] 线程3
         2017-04-02 10:55:48.721 LockKata1[1855:100893] 线程2
         2017-04-02 10:55:48.725 LockKata1[1855:100893] 线程1
    
         */
    }
    #pragma mark----@synchronized 条件锁
    
    - (void) synchronized_hsk{
        
        //线程1
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            
            @synchronized (self) {
                sleep(2);
                NSLog(@"线程1");
            }
        });
        //线程2
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            @synchronized (self) {
                NSLog(@"线程2");
            }
            
        });
        /*
         2017-04-02 11:03:11.972 LockKata1[1885:104889] 线程2
         2017-04-02 11:03:14.013 LockKata1[1885:104890] 线程1
    
         */
    }
    void NSConditonLock_hsk(){
        
        NSConditionLock *cLock =[[NSConditionLock alloc]initWithCondition:0];
        //线程1
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            
            if ([cLock tryLockWhenCondition:0]) {
                NSLog(@"线程1");
                [cLock unlockWithCondition:1];
            }else{
                NSLog(@"失败");
            }
        });
        //线程2
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [cLock lockWhenCondition:3];
            NSLog(@"线程2");
            [cLock unlockWithCondition:2];
            
        });
        //线程3
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [cLock lockWhenCondition:1];
            NSLog(@"线程3");
            [cLock unlockWithCondition:3];
            
        });
        /*
         我们在初始化NSConditionLock对象时,给了他的标示为0
         执行tryLockWhenCondition:时,我们传入的条件标示也是0,所以线程1加锁成功
         执行 unlockWithCondition:时,这时候会把condition由0 修改为1
         因为condition修改为了1,会先走到线程3,然后线程3又将condition修改为3,最后走了线程2的流程
         
         从上面的结果我们可以发现,NSConditionLock还可以实现任务之间的依赖。
         控制台日志:
         2017-04-02 11:10:25.099 LockKata1[1914:108665] 线程1
         2017-04-02 11:10:25.101 LockKata1[1914:108667] 线程3
         2017-04-02 11:10:25.101 LockKata1[1914:108664] 线程2
    */
    }
    - (void)viewDidLoad {
        
         [super viewDidLoad];
        
        NSConditonLock_hsk();
    
        
    }
    
    
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    @end
    
    

    相关文章

      网友评论

          本文标题:iOS开发过程中的各种锁

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