iOS开发过程中的各种锁

2017-04-02  本文已影响52人  SDBridge

各种锁的效率图

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

上一篇下一篇

猜你喜欢

热点阅读