iOS 開發(fā)過(guò)程中8種鎖

8lock.png

OSSpinLock

OSSpinLock 自旋鎖,不會(huì)讓等待的線程進(jìn)入睡眠狀態(tài),效率高。
OSSpinLock 不能保證安全。系統(tǒng)維護(hù)了5個(gè)不同的線程優(yōu)先級(jí)/QoS: background蛙讥,utility,default灭衷,user-initiated次慢,user-interactive。高優(yōu)先級(jí)線程始終會(huì)在低優(yōu)先級(jí)線程前執(zhí)行翔曲,一個(gè)線程不會(huì)受到比它更低優(yōu)先級(jí)線程的干擾迫像。這種線程調(diào)度算法會(huì)差生潛在的優(yōu)先級(jí)反轉(zhuǎn)問(wèn)題,從而破壞spin Lock
優(yōu)先級(jí)反轉(zhuǎn):如果一個(gè)低優(yōu)先級(jí)的線程獲得鎖并訪問(wèn)共享資源瞳遍,這時(shí)一個(gè)高優(yōu)先級(jí)的線程也嘗試獲得該鎖闻妓,它會(huì)處于spin lock 的忙等狀態(tài)從而占用大量CPU。此時(shí)低優(yōu)先級(jí)線程無(wú)法與高優(yōu)先級(jí)線程爭(zhēng)奪CPU時(shí)間掠械,從而導(dǎo)致任務(wù)遲遲完不成由缆、無(wú)法釋放Lock。

最終的結(jié)論就是猾蒂,除非開發(fā)者能保證訪問(wèn)鎖的線程全部都處于同一優(yōu)先級(jí)均唉,否則 iOS 系統(tǒng)中所有類型的自旋鎖都不能再使用了

OS_SPINLOCK_INIT:默認(rèn)值為0,在locked狀態(tài)時(shí)婚夫,就會(huì)大于0浸卦,unlocked 狀態(tài)下為 0 
OSSpinLockLock(&oslock):上鎖,參數(shù)為OSSpinLock 地址
OSSpinLockUnlock(&oslock):解鎖案糙,參數(shù)為OSSpinLock 地址 
OSSpinLockTry(&oslock):嘗試加鎖,可以加鎖則立即加鎖靴庆,并返回YES时捌,反之返回NO。

dispatch_semaphore 信號(hào)量

dispatch_semaphore_create(1) 傳值必須 >=0 ,若傳為0炉抒,則阻塞線程并等待
dispatch_semaphore_wait(signal, overTime): 可以理解為lock奢讨,會(huì)使得signal值 -1
dispatch_semaphore_signal(signal): 可以理解為unlock, 會(huì)使得signal值 +1

phread_mutex

static pthread_mutex_t pLock;
pthread_mutex_init(&pLock, NULL);
pthread_mutex_lock(&pLock);
pthread_mutex_unlock(&pLock);

#pthread_mutex 中也有個(gè)pthread_mutex_trylock(&pLock), 和上面提到的OSSpinLockTry(&oslock)區(qū)別在于,前者可以加鎖時(shí)返回的是0焰薄,否則返回一個(gè)錯(cuò)誤提示碼拿诸;后者返回的YES 和 NO

pthread_mutex(recursive)遞歸鎖

加鎖后只能有一個(gè)線程訪問(wèn)該對(duì)象扒袖,后面的線程需要排隊(duì),并且 lock 和 unlock 是對(duì)應(yīng)出現(xiàn)的亩码,同一線程多次 lock 是不允許的季率,而遞歸鎖允許同一個(gè)線程在未釋放其擁有的鎖時(shí)反復(fù)對(duì)該鎖進(jìn)行加鎖操作

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); //銷毀一個(gè)屬性對(duì)象描沟,在重新進(jìn)行初始化之前該結(jié)構(gòu)不能重新使用

pthread_mutex_lock(&pLock);
pthread_mutex_unlock(&pLock);

NSLock

lock 飒泻、unlock 、tryLock 能加鎖返回YES并執(zhí)行加鎖操作吏廉,相當(dāng)于lock泞遗,反之返回NO

NSLock *lock = [NSLock new];
[lock lock]
[lock unlock]

NSCondition

wait:進(jìn)入等待狀態(tài)
waitUntilDate:讓一個(gè)線程等待一定的時(shí)間
signal: 喚醒一個(gè)等待的線程
broadcast: 喚醒所有等待的線程

// 等待2秒
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]];
    NSLog(@"線程1");
    [cLock unlock];
});

// 喚醒一個(gè)等待線程
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(@"喚醒一個(gè)等待的線程");
    [cLock signal];
});

// 喚醒所有等待的線程
.........    
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    sleep(2);
    NSLog(@"喚醒所有等待的線程");
    [cLock broadcast];
});

NSRecursiveLock 遞歸鎖

NSRecursiveLock *rLock = [NSRecursiveLock new];
[rLock lock];
[rLock unlock];

@synchronized

//線程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");
    }
});

NSConditionLock 條件鎖

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];
});

參考:
ios 中會(huì)使用到的鎖

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市席覆,隨后出現(xiàn)的幾起案子史辙,更是在濱河造成了極大的恐慌,老刑警劉巖佩伤,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件聊倔,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡畦戒,警方通過(guò)查閱死者的電腦和手機(jī)方库,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)障斋,“玉大人纵潦,你說(shuō)我怎么就攤上這事±罚” “怎么了邀层?”我有些...
    開封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)遂庄。 經(jīng)常有香客問(wèn)我寥院,道長(zhǎng),這世上最難降的妖魔是什么涛目? 我笑而不...
    開封第一講書人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任秸谢,我火速辦了婚禮,結(jié)果婚禮上霹肝,老公的妹妹穿的比我還像新娘估蹄。我一直安慰自己,他們只是感情好沫换,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開白布臭蚁。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪垮兑。 梳的紋絲不亂的頭發(fā)上冷尉,一...
    開封第一講書人閱讀 49,749評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音系枪,去河邊找鬼雀哨。 笑死,一個(gè)胖子當(dāng)著我的面吹牛嗤无,可吹牛的內(nèi)容都是我干的震束。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼当犯,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼垢村!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起嚎卫,我...
    開封第一講書人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤嘉栓,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后拓诸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體侵佃,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年奠支,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了馋辈。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡倍谜,死狀恐怖迈螟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情尔崔,我是刑警寧澤答毫,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站季春,受9級(jí)特大地震影響洗搂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜载弄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一耘拇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧宇攻,春花似錦驼鞭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至亲桥,卻和暖如春洛心,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背题篷。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工词身, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人番枚。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓法严,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親葫笼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子深啤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

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

  • 鎖是一種同步機(jī)制,用于多線程環(huán)境中對(duì)資源訪問(wèn)的限制iOS中常見鎖的性能對(duì)比圖(摘自:ibireme): iOS鎖的...
    LiLS閱讀 1,510評(píng)論 0 6
  • 線程安全是怎么產(chǎn)生的 常見比如線程內(nèi)操作了一個(gè)線程外的非線程安全變量路星,這個(gè)時(shí)候一定要考慮線程安全和同步溯街。 - (v...
    幽城88閱讀 653評(píng)論 0 0
  • 轉(zhuǎn)載:談 iOS 的鎖 又到了春天挪坑的季節(jié),想起多次被問(wèn)及到鎖的概念洋丐,決定好好總結(jié)一番呈昔。 翻看目前關(guān)于 iOS ...
    小鯤鵬閱讀 519評(píng)論 0 0
  • 22天 可以買機(jī)械鍵盤了 開始明白最難的不是開始 是走在路上 沒(méi)有方向的迷茫 面對(duì)各種質(zhì)疑 想停下腳步 可是 沒(méi)有...
    emma佳小佳閱讀 196評(píng)論 0 0
  • 讀創(chuàng)新者的窘境有感 為什么大型企業(yè)無(wú)法基業(yè)長(zhǎng)青? 從規(guī)模這本書里友绝,我們看到企業(yè)更像一個(gè)生命體堤尾,有類似生命體的特征,...
    開不了口讓她知道閱讀 183評(píng)論 0 2