iOS开发过程中的各种锁

各种锁的效率图

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容