iOS中的鎖簡(jiǎn)單總結(jié)

由于之前開發(fā)中用到了鎖這個(gè)東西蠕趁,加上這個(gè)知識(shí)在之前的項(xiàng)目中用之甚少懦底,所以對(duì)于此想做一下在百度網(wǎng)上文章過程中的再一次了解中的簡(jiǎn)單總結(jié)雅任。

基本思路就三點(diǎn):1:iOS中有幾種常用的鎖

             2:幾種鎖的性能及個(gè)別鎖的簡(jiǎn)單使用 

             3:對(duì)于常用鎖中互斥鎖(NSLock 和@synchronized)和自旋鎖的區(qū)別

首先要知道鎖是一種同步機(jī)制懈息,用于在存在多線程環(huán)境中實(shí)施對(duì)資源訪問限制肾档。其中有互斥鎖、對(duì)象所辫继、遞歸鎖怒见、條件鎖、自旋鎖姑宽、信號(hào)量實(shí)現(xiàn)加鎖這幾種遣耍。他們分別有自己的處理機(jī)制故而性能也不盡相同,具體性能由快到慢簡(jiǎn)單總結(jié)如下:

OSSpinLock(性能最高但不再安全 具體使用方式也無須過于了解炮车,iOS SDK里無OSSpinLock頭文件可導(dǎo) 用不了)>

dispatch_semaphore (信號(hào)量加鎖)> pthread_mutex (互斥鎖)> NSLock (對(duì)象鎖 也是互斥鎖的一種)>NSRecursiveLock (遞歸鎖) >NSConditionLock (條件鎖)> @synchronized (互斥鎖)

以下列舉簡(jiǎn)單使用的買票實(shí)例 http://www.reibang.com/p/1e59f0970bf5 (從此文章中粘入幾個(gè)實(shí)例引用便于自己觀看回顧)

@synchronized 是一個(gè) OC 層面的鎖舵变, 主要是通過犧牲性能換來語法上的簡(jiǎn)潔,@synchronized 后面需要緊跟一個(gè) OC 對(duì)象瘦穆,它實(shí)際上是把這個(gè)對(duì)象當(dāng)做鎖來使用纪隙。這是通過一個(gè)哈希表來實(shí)現(xiàn)的,OC 在底層使用了一個(gè)互斥鎖的數(shù)組(你可以理解為鎖池)扛或,通過對(duì)對(duì)象去哈希值來得到對(duì)應(yīng)的互斥鎖绵咱。

//設(shè)置票的數(shù)量為5
    _tickets = 5;
    
    //線程1
    dispatch_async(self.concurrentQueue, ^{
        [self saleTickets];
    });
    
    //線程2
    dispatch_async(self.concurrentQueue, ^{
        [self saleTickets];
    });

- (void)saleTickets
{
    while (1) {
        @synchronized(self) {
            [NSThread sleepForTimeInterval:1];
            if (_tickets > 0) {
                _tickets--;
                NSLog(@"剩余票數(shù)= %ld, Thread:%@",_tickets,[NSThread currentThread]);
            } else {
                NSLog(@"票賣完了  Thread:%@",[NSThread currentThread]);
                break;
            }
        }
    }
}

NSLock 互斥鎖只是在內(nèi)部封裝了一個(gè) pthread_mutex,屬性為PTHREAD_MUTEX_ERRORCHECK熙兔,它會(huì)損失一定性能換來錯(cuò)誤提示悲伶。不能多次調(diào)用lock

//設(shè)置票的數(shù)量為5
   _tickets = 5;
   
   //創(chuàng)建鎖
   _mutexLock = [[NSLock alloc] init];
   
   //線程1
   dispatch_async(self.concurrentQueue, ^{
       [self saleTickets];
   });
   
   //線程2
   dispatch_async(self.concurrentQueue, ^{
       [self saleTickets];
   });

- (void)saleTickets
{

   while (1) {
       [NSThread sleepForTimeInterval:1];
       //加鎖
       [_mutexLock lock];
       if (_tickets > 0) {
           _tickets--;
           NSLog(@"剩余票數(shù)= %ld, Thread:%@",_tickets,[NSThread currentThread]);        
       } else {
           NSLog(@"票賣完了  Thread:%@",[NSThread currentThread]);
           break;
       }
       //解鎖
       [_mutexLock unlock];
   }
}

NSConditionLock (條件鎖)

//主線程中
    NSConditionLock *theLock = [[NSConditionLock alloc] init];
    
    //線程1
    dispatch_async(self.concurrentQueue, ^{
        for (int i=0;i<=3;i++)
        {
            [theLock lock];
            NSLog(@"thread1:%d",i);
            sleep(1);
            [theLock unlockWithCondition:i];
        }
    });
    
    //線程2
    dispatch_async(self.concurrentQueue, ^{
        [theLock lockWhenCondition:2];
        NSLog(@"thread2");
        [theLock unlock];
    });

NSRecursiveLock (遞歸鎖)

//創(chuàng)建鎖
    _rsLock = [[NSRecursiveLock alloc] init];
    
   //線程1
    dispatch_async(self.concurrentQueue, ^{
        static void(^TestMethod)(int);
        TestMethod = ^(int value)
        {
            [_rsLock lock];
            if (value > 0)
            {
                [NSThread sleepForTimeInterval:1];
                TestMethod(value--);
            }
            [_rsLock unlock];
        };
        
        TestMethod(5);
    });

pthread_mutex 互斥鎖 需要導(dǎo)入#include <pthread.h>

__block pthread_mutex_t mutex;
    pthread_mutex_init(&mutex, NULL);
    
    //線程1
    dispatch_async(self.concurrentQueue), ^{
        pthread_mutex_lock(&mutex);
        NSLog(@"任務(wù)1");
        sleep(2);
        pthread_mutex_unlock(&mutex);
    });
    
    //線程2
    dispatch_async(self.concurrentQueue), ^{
        sleep(1);
        pthread_mutex_lock(&mutex);
        NSLog(@"任務(wù)2");
        pthread_mutex_unlock(&mutex);
    });

dispatch_semaphore 信號(hào)量實(shí)現(xiàn)加鎖

// 創(chuàng)建信號(hào)量
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
    //線程1
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
         NSLog(@"任務(wù)1");
        sleep(10);
        dispatch_semaphore_signal(semaphore);
    });
    
    //線程2
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        sleep(1);
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        NSLog(@"任務(wù)2");
        dispatch_semaphore_signal(semaphore);
    });

自旋鎖

bool lock = false; // 一開始沒有鎖上,任何線程都可以申請(qǐng)鎖
do {
    while(test_and_set(&lock); // test_and_set 是一個(gè)原子操作
        Critical section  // 臨界區(qū)
    lock = false; // 相當(dāng)于釋放鎖黔姜,這樣別的線程可以進(jìn)入臨界區(qū)
        Reminder section // 不需要鎖保護(hù)的代碼        
}

對(duì)于自旋鎖和互斥鎖二者的區(qū)別
相同點(diǎn)在于:都能保證同一時(shí)間只有一個(gè)線程訪問共享資源 保證安全
不同點(diǎn)在于:1自旋鎖效率高于互斥鎖
2如果共享數(shù)據(jù)已有其他線程加鎖了拢切,互斥鎖會(huì)使線程進(jìn)入休眠狀態(tài)等待解鎖,如果資源解鎖秆吵,則線程被喚醒淮椰。而自旋鎖會(huì)使線程以死循環(huán)的方式等待解鎖,如果資源解鎖,則另一個(gè)線程會(huì)立即執(zhí)行

PS:atomic內(nèi)部為互斥鎖 ->其中setter方法中多了個(gè)@synchronized(self){} <-等當(dāng)前對(duì)象操作完畢會(huì)合成確定值

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末主穗,一起剝皮案震驚了整個(gè)濱河市泻拦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌忽媒,老刑警劉巖争拐,帶你破解...
    沈念sama閱讀 212,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異晦雨,居然都是意外死亡架曹,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門闹瞧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绑雄,“玉大人,你說我怎么就攤上這事奥邮⊥蛭” “怎么了?”我有些...
    開封第一講書人閱讀 158,369評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵洽腺,是天一觀的道長(zhǎng)脚粟。 經(jīng)常有香客問我,道長(zhǎng)蘸朋,這世上最難降的妖魔是什么核无? 我笑而不...
    開封第一講書人閱讀 56,799評(píng)論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮度液,結(jié)果婚禮上厕宗,老公的妹妹穿的比我還像新娘。我一直安慰自己堕担,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評(píng)論 6 386
  • 文/花漫 我一把揭開白布曲聂。 她就那樣靜靜地躺著霹购,像睡著了一般。 火紅的嫁衣襯著肌膚如雪朋腋。 梳的紋絲不亂的頭發(fā)上齐疙,一...
    開封第一講書人閱讀 50,096評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音旭咽,去河邊找鬼贞奋。 笑死,一個(gè)胖子當(dāng)著我的面吹牛穷绵,可吹牛的內(nèi)容都是我干的轿塔。 我是一名探鬼主播,決...
    沈念sama閱讀 39,159評(píng)論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼勾缭!你這毒婦竟也來了揍障?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,917評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤俩由,失蹤者是張志新(化名)和其女友劉穎毒嫡,沒想到半個(gè)月后锰瘸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體揪阶,經(jīng)...
    沈念sama閱讀 44,360評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡假哎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評(píng)論 2 327
  • 正文 我和宋清朗相戀三年俄周,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了崎弃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片想括。...
    茶點(diǎn)故事閱讀 38,814評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡婶溯,死狀恐怖跌穗,靈堂內(nèi)的尸體忽然破棺而出痘系,到底是詐尸還是另有隱情菲嘴,我是刑警寧澤,帶...
    沈念sama閱讀 34,509評(píng)論 4 334
  • 正文 年R本政府宣布汰翠,位于F島的核電站龄坪,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏复唤。R本人自食惡果不足惜健田,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望佛纫。 院中可真熱鬧妓局,春花似錦、人聲如沸呈宇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽甥啄。三九已至存炮,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蜈漓,已是汗流浹背穆桂。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評(píng)論 1 267
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留融虽,地道東北人享完。 一個(gè)月前我還...
    沈念sama閱讀 46,641評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像有额,于是被迫代替她去往敵國(guó)和親般又。 傳聞我的和親對(duì)象是個(gè)殘疾皇子彼绷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評(píng)論 2 351

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

  • 鎖是一種同步機(jī)制,用于多線程環(huán)境中對(duì)資源訪問的限制iOS中常見鎖的性能對(duì)比圖(摘自:ibireme): iOS鎖的...
    LiLS閱讀 1,512評(píng)論 0 6
  • 前言 在多線程開發(fā)中倒源,常會(huì)遇到多個(gè)線程訪問修改數(shù)據(jù)苛预。為了防止數(shù)據(jù)不一致或數(shù)據(jù)污染,通常采用加鎖機(jī)制來保證線程安全笋熬。...
    趙夢(mèng)楠閱讀 931評(píng)論 0 5
  • iOS線程安全的鎖與性能對(duì)比 一热某、鎖的基本使用方法 1.1、@synchronized 這是我們最熟悉的枷鎖方式胳螟,...
    Jacky_Yang閱讀 2,212評(píng)論 0 17
  • 在平時(shí)的開發(fā)中經(jīng)常使用到多線程昔馋,在使用多線程的過程中,難免會(huì)遇到資源競(jìng)爭(zhēng)的問題糖耸,那我們?cè)趺磥肀苊獬霈F(xiàn)這種問題那秘遏? ...
    IAMCJ閱讀 3,092評(píng)論 2 25
  • 也許當(dāng)我們開始尊重我們認(rèn)為無意識(shí)的生命的開始,我們才開始了真正的尊重嘉竟。 剛剛出生的孩子邦危,我們到底該怎...
    寧?kù)o的SKY閱讀 183評(píng)論 0 0