說到多線程就不得不提多線程中的鎖機(jī)制,多線程操作過程中往往多個(gè)線程是并發(fā)執(zhí)行的,同一個(gè)資源可能被多個(gè)線程同時(shí)訪問,造成資源搶奪,這個(gè)過程中如果沒有鎖機(jī)制往往會(huì)造成重大問題。舉例來說,每年春節(jié)都是一票難求,在12306買票的過程中,成百上千的票瞬間就消失了。不妨假設(shè)某輛車有1千張票,同時(shí)有幾萬人在搶這列車的車票,順利的話前面的人都能買到票。但是如果現(xiàn)在只剩下一張票了,而同時(shí)還有幾千人在購買這張票,雖然在進(jìn)入購票環(huán)節(jié)的時(shí)候會(huì)判斷當(dāng)前票數(shù),但是當(dāng)前已經(jīng)有100個(gè)線程進(jìn)入購票的環(huán)節(jié),每個(gè)線程處理完票數(shù)都會(huì)減1,100個(gè)線程執(zhí)行完當(dāng)前票數(shù)為-99,遇到這種情況很明顯是不允許的。
要解決資源搶奪問題在iOS中有常用的有兩種方法:一種是使用NSLock同步鎖,另一種是使用@synchronized代碼塊。兩種方法實(shí)現(xiàn)原理是類似的,只是在處理上代碼塊使用起來更加簡單。
NSLock對(duì)象實(shí)現(xiàn)了NSLocking PRotocol,包含幾個(gè)方法: lock,加鎖 unlock,解鎖 tryLock,嘗試加鎖,如果失敗了,并不會(huì)阻塞線程,只是立即返回NO lockBeforeDate:,在指定的date之前暫時(shí)阻塞線程(如果沒有獲取鎖的話),如果到期還沒有獲取鎖,則線程被喚醒,函數(shù)立即返回NO 比如:
NSLock *theLock = [[NSLock alloc] init]; if ([theLock lock]) { //do something here [theLock unlock]; }會(huì)自動(dòng)對(duì)參數(shù)對(duì)象加鎖,保證臨界區(qū)內(nèi)的代碼線程安全
@synchronized(self) { // 這段代碼對(duì)其他 @synchronized(self) 都是互斥的 // self 指向同一個(gè)對(duì)象 }方法三,NSRecursiveLock,遞歸鎖 NSRecursiveLock,多次調(diào)用不會(huì)阻塞已獲取該鎖的線程。
NSRecursiveLock *theLock = [[NSRecursiveLock alloc] init]; void MyRecursiveFunction(int value) { [theLock lock]; if (value != 0) { --value; MyRecursiveFunction(value); } [theLock unlock]; } MyRecursiveFunction(5);方法四,NSConditionLock,條件鎖 NSConditionLock,條件鎖,可以設(shè)置條件
//公共部分 id condLock = [[NSConditionLock alloc] initWithCondition:NO_DATA]; //線程一,生產(chǎn)者 while(true) { [condLock lockWhenCondition:NO_DATA]; //生產(chǎn)數(shù)據(jù) [condLock unlockWithCondition:HAS_DATA]; } //線程二,消費(fèi)者 while (true) { [condLock lockWhenCondition:HAS_DATA]; //消費(fèi) [condLock unlockWithCondition:NO_DATA]; }方法五,NSDistributedLock,分布鎖 NSDistributedLock,分布鎖,文件方式實(shí)現(xiàn),可以跨進(jìn)程 用tryLock方法獲取鎖。 用unlock方法釋放鎖。 如果一個(gè)獲取鎖的進(jìn)程在釋放鎖之前掛了,那么鎖就一直得不到釋放了,此時(shí)可以通過breakLock強(qiáng)行獲取鎖。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注