iOS開發(fā)過程中的各種鎖

各種鎖的效率圖

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 準(zhǔn)備上鎖 當(dāng)前線程 ");
                 
                 OSSpinLockLock(&oslosk);
                 sleep(4);
                 NSLog(@"線程1");
                 OSSpinLockUnlock(&oslosk);
                 NSLog(@"線程1 解鎖成功");
                 NSLog(@"-----------------------------");
         
         
         
         });
         dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                 NSLog(@"線程2 準(zhǔn)備上鎖");
                 OSSpinLockLock(&oslosk);
                 NSLog(@"線程2");
                 OSSpinLockUnlock(&oslosk);
                 NSLog(@"線程2 解鎖成功");
         });
 
 }
 */
/*
 控制臺:
 
 function:__OSSpinLockh_hsk_block_invoke line:26 content:線程1 準(zhǔn)備上鎖 當(dāng)前線程  ??Multi Threaded
 
 function:__OSSpinLockh_hsk_block_invoke.16 line:39 content:線程2 準(zhǔn)備上鎖 ??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,時間到后會執(zhí)行其后的語句
    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 發(fā)送信號");
    });
    
    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 發(fā)送信號");
    
    });
    
    /*
     傳入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 發(fā)送信號
     2017-04-02 09:02:26.194 LockKata1[1336:38096] 線程2
     2017-04-02 09:02:26.195 LockKata1[1336:38096] 線程2 發(fā)送信號
     
     某一次:
     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 發(fā)送信號
     2017-04-02 09:03:11.100 LockKata1[1353:38735] 線程2
     2017-04-02 09:03:11.101 LockKata1[1353:38735] 線程2 發(fā)送信號
     
     傳入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 發(fā)送信號
     2017-04-02 09:06:56.946 LockKata1[1376:41653] 線程1 發(fā)送信號
     
     */
    
}

#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), ^{
        
        //子線程網(wǎng)絡(luò)請求
        NSLog(@"線程1 準(zhǔn)備上鎖");
        pthread_mutex_lock(&pLock);
        sleep(3);
        NSLog(@"線程1");
        pthread_mutex_unlock(&pLock);
    
    });
    //線程2
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        //子線程網(wǎng)絡(luò)請求
        NSLog(@"線程2    準(zhǔn)備上鎖");
        pthread_mutex_lock(&pLock);
        NSLog(@"線程2");
        pthread_mutex_unlock(&pLock);
    
    });
    /*
     lock 和unlock 成對出現(xiàn)
     
     */
    /*
     控制臺日志:
     2017-04-02 09:33:21.575 LockKata1[1493:57547] 線程2    準(zhǔn)備上鎖
     2017-04-02 09:33:21.575 LockKata1[1493:57545] 線程1 準(zhǔn)備上鎖
     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并且給它賦予默認(rèn)值
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);//設(shè)置鎖類型虱岂,這里設(shè)置為遞歸鎖
    pthread_mutex_init(&pLock, &attr);
    pthread_mutexattr_destroy(&attr);//銷毀一個屬性對象,在重新進(jìn)行初始化之前改結(jié)構(gòu)不能重新使用
    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) 初始化會出現(xiàn)死鎖的情況菠红,遞歸鎖能很好的避免這種情況的死鎖第岖;

     */
    /*
     控制臺日志:
     
     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--經(jīng)典錯誤例子
//我在這里寫的C方法 在AppDelegate.m方法中一樣能調(diào)用,(*@ο@*) 哇~试溯,夸類了蔑滓,還是 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是遞歸調(diào)用的键袱。所以每次進(jìn)入這個block時燎窘,都會去加一次鎖,而從第二次開始蹄咖,由于鎖已經(jīng)被使用了且沒有解鎖褐健,所以它需要等待鎖被解除,這樣就導(dǎo)致了死鎖澜汤,線程被阻塞住了蚜迅。
     控制臺日志:
     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對象時,給了他的標(biāo)示為0
     執(zhí)行tryLockWhenCondition:時银亲,我們傳入的條件標(biāo)示也是0慢叨,所以線程1加鎖成功
     執(zhí)行 unlockWithCondition:時纽匙,這時候會把condition由0 修改為1
     因?yàn)閏ondition修改為了1务蝠,會先走到線程3,然后線程3又將condition修改為3烛缔,最后走了線程2的流程
     
     從上面的結(jié)果我們可以發(fā)現(xiàn)馏段,NSConditionLock還可以實(shí)現(xiàn)任務(wù)之間的依賴。
     控制臺日志:
     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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末践瓷,一起剝皮案震驚了整個濱河市院喜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌晕翠,老刑警劉巖喷舀,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異淋肾,居然都是意外死亡硫麻,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門樊卓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拿愧,“玉大人,你說我怎么就攤上這事碌尔〗焦迹” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵唾戚,是天一觀的道長柳洋。 經(jīng)常有香客問我,道長叹坦,這世上最難降的妖魔是什么熊镣? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上轧钓,老公的妹妹穿的比我還像新娘序厉。我一直安慰自己,他們只是感情好毕箍,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布弛房。 她就那樣靜靜地躺著,像睡著了一般而柑。 火紅的嫁衣襯著肌膚如雪文捶。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天媒咳,我揣著相機(jī)與錄音粹排,去河邊找鬼。 笑死涩澡,一個胖子當(dāng)著我的面吹牛顽耳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播妙同,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼射富,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了粥帚?” 一聲冷哼從身側(cè)響起胰耗,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎芒涡,沒想到半個月后柴灯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡费尽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年赠群,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片依啰。...
    茶點(diǎn)故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡乎串,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出速警,到底是詐尸還是另有隱情叹誉,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布闷旧,位于F島的核電站长豁,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏忙灼。R本人自食惡果不足惜匠襟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一钝侠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧酸舍,春花似錦帅韧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至淮阐,卻和暖如春叮阅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背泣特。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留状您,地道東北人勒叠。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像竞阐,于是被迫代替她去往敵國和親缴饭。 傳聞我的和親對象是個殘疾皇子暑劝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內(nèi)容