版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
iOS程序員面試分類模擬12簡答題1.
什么是線程?線程與進程有什么區(qū)別?為什么要使用多線程?正確答案:線程指程序在執(zhí)行過程中,能夠執(zhí)行程序代碼的一個執(zhí)行單元。線程主要有4種狀態(tài):運行、就緒、掛起(江南博哥)、結(jié)束。
進程指一段正在執(zhí)行的程序。而線程有時候也被稱為輕量級進程,是程序執(zhí)行的最小單元。一個進程可以擁有多個線程,各個線程之間共享程序的內(nèi)存空間(代碼段、數(shù)據(jù)段和堆空間)及一些進程級的資源(例如打開的文件),但是各個線程擁有自己的??臻g。進程與線程的關(guān)系如圖所示。
進程與線程的關(guān)系
在操作系統(tǒng)級別上,程序的執(zhí)行都是以進程為單位的,而每個進程中通常都會有多個線程互不影響地并發(fā)執(zhí)行,那么為什么要使用多線程呢?其實,使用多線程為程序研發(fā)帶來了巨大的便利。具體而言,有以下幾個方面的內(nèi)容:
1)使用多線程可以減少程序的響應(yīng)時間。在單線程(單線程指程序執(zhí)行過程中只有一個有效操作的序列,不同操作之間都有明確的執(zhí)行先后順序)的情況下,如果某個操作很耗時,或者陷入長時間的等待(如等待網(wǎng)絡(luò)響應(yīng)),那么此時程序?qū)⒉粫憫?yīng)鼠標(biāo)和鍵盤等操作,使用多線程后,可以把這個耗時的線程分配到一個單獨的線程去執(zhí)行,使得程序具備了更好的交互性。
2)與進程相比,線程的創(chuàng)建和切換開銷更小。由于啟動一個新的線程必須給這個線程分配獨立的地址空間,建立許多數(shù)據(jù)結(jié)構(gòu)來維護線程代碼段、數(shù)據(jù)段等信息,而運行于同一進程內(nèi)的線程共享代碼段、數(shù)據(jù)段,所以線程的啟動或切換的開銷比進程要少很多。同時多線程在數(shù)據(jù)共享方面效率非常高。
3)多CPU或多核計算機本身就具有執(zhí)行多線程的能力,如果使用單個線程,那么將無法重復(fù)利用計算機資源,造成資源的巨大浪費。因此,在多CPU計算機上使用多線程能提高CPU的利用率。
4)使用多線程能簡化程序的結(jié)構(gòu),使程序便于理解和維護。一個非常復(fù)雜的進程可以分成多個線程來執(zhí)行。
2.
如何理解多線程?正確答案:多線程(multithreading)指從軟件或者硬件上實現(xiàn)多個線程并發(fā)執(zhí)行的技術(shù)。具有多線程能力的計算機因有硬件的支持而能夠在同一時間執(zhí)行多個線程,進而提升整體處理性能。要深入了解iOS中的多線程技術(shù),先需要了解以下幾個概念。
1.進程
每個正在系統(tǒng)上運行的程序都是一個進程。每個進程之間是相互獨立的,每個進程均運行在其專用且受保護的內(nèi)存空間內(nèi)。進程在系統(tǒng)內(nèi)存中的關(guān)系如圖所示。
系統(tǒng)內(nèi)存中的進程
通過“活動監(jiān)視器”可以查看Mac系統(tǒng)中開啟的所有進程(見圖)。
活動監(jiān)視器中的進程
2.線程
線程是一組指令的集合,或者是程序的特殊段,它可以在程序里獨立執(zhí)行。每個進程包含至少一個線程。線程基本上是輕量級的進程,它負(fù)責(zé)在單個程序中執(zhí)行多個任務(wù)。通常由系統(tǒng)負(fù)責(zé)多個線程的調(diào)度和執(zhí)行。
需要注意的是,在同一個線程中執(zhí)行的任務(wù)是串行的。也就是說,在同一時間內(nèi),一個線程只能執(zhí)行一個任務(wù)。
線程是程序中一個單一的順序控制流程。在單個程序中同時運行多個線程完成不同的工作,稱為多線程。多線程技術(shù)主要是為了充分利用CPU,提高程序的執(zhí)行效率。多線程之間的關(guān)系如圖所示。
多線程之間的關(guān)系
事實上,在同一時間,CPU只能處理一條線程,只有一條線程在執(zhí)行。多線程的并發(fā)執(zhí)行,其實就是CPU快速地在多條線程之間調(diào)度。如果CPU調(diào)度線程的速度足夠快,那么就會產(chǎn)生多條線程并發(fā)執(zhí)行的假象。
多線程技術(shù)的優(yōu)點如下:
1)可以很大程度上提高程序的執(zhí)行效率,提高程序的響應(yīng)速度。
2)使用線程可以把占據(jù)時間長的程序中的任務(wù)放到后臺去處理,這樣就不會阻塞程序主線程,用戶體驗更好(耗時操作會卡住主線程,嚴(yán)重影響UI的流暢度)。
3)提高計算機資源的利用率,如:更加充分利用內(nèi)存,多CPU計算機上提高CPU利用率。
4)將進程分塊,優(yōu)化簡化程序邏輯結(jié)構(gòu)。
多線程技術(shù)的缺點如下:
1)多線程程序的代碼會更加復(fù)雜、難讀,增加交接和維護難度。
2)創(chuàng)建和調(diào)度線程會有額外的開銷,線程越多,開銷越大,甚至反而降低程序的性能。
3)通常模型數(shù)據(jù)是在多個線程間共享的,需要防止線程死鎖情況的發(fā)生。
因此,在實際使用多線程時,需要適當(dāng)開啟線程,當(dāng)線程使用完成后,需要及時釋放資源。在最新的iOS技術(shù)中,已經(jīng)很少需要直接操作線程了,因為蘋果公司已經(jīng)將大部分復(fù)雜的操作封裝好。
3.
如何理解HTTP協(xié)議?正確答案:超文本傳輸協(xié)議(HyperTextTransferProtocol,HTTP)是互聯(lián)網(wǎng)上應(yīng)用最為廣泛的一種網(wǎng)絡(luò)協(xié)議。簡單來說,HTTP是客戶端和服務(wù)器端之間請求和應(yīng)答的標(biāo)準(zhǔn),它可以使瀏覽器(或其他客戶端)更加高效,使網(wǎng)絡(luò)傳輸減少。它不僅保證計算機正確快速地傳輸超文本文檔,還確定傳輸文檔中的哪一部分,以及哪部分內(nèi)容優(yōu)先顯示(如文本先于圖形)等。
一次HTTP操作稱為一個事務(wù),其工作過程可分為4步:
1)客戶端與服務(wù)器需要建立連接。例如,單擊某個超鏈接后,瀏覽器和服務(wù)器將建立通信連接。
2)建立連接后,客戶端發(fā)送一個請求給服務(wù)器,請求方式的格式為:統(tǒng)一資源標(biāo)識符(URL)、協(xié)議版本號,后邊是MIME信息包括請求修飾符、客戶端信息和可能的內(nèi)容。
3)服務(wù)器接到請求后,給予相應(yīng)的響應(yīng)信息,其格式為一個狀態(tài)行,包括信息的協(xié)議版本號、一個成功或錯誤的代碼,后邊是MIME信息包括服務(wù)器信息、實體信息和可能的內(nèi)容。
4)客戶端接收服務(wù)器所返回的信啟、通過瀏覽器顯示在用戶的顯示屏上,然后客戶機與服務(wù)器斷開連接。
如果在以上過程中的某一步出現(xiàn)錯誤,那么產(chǎn)生錯誤的信息將返回到客戶端,由顯示屏輸出。對于用戶來說,這些過程是由HTTP自己完成的,用戶只要用鼠標(biāo)單擊,等待信息顯示就可以了。
通常HTTP消息包括客戶端向服務(wù)器的請求消息和服務(wù)器向客戶端的響應(yīng)消息。這兩種類型的消息由一個起始行,一個或者多個頭域,一個指示頭域結(jié)束的空行和可選的消息體組成。HTTP的頭域包括通用頭、請求頭、響應(yīng)頭和實體頭4個部分。每個頭域由一個域名、冒號(:)和域值組成。域名是大小寫無關(guān)的,域值前可以添加任何數(shù)量的空格符,頭域可以被擴展為多行,在每行開始處,使用至少一個空格或制表符。
一個完整的由客戶端發(fā)給服務(wù)器的HTTP請求包含以下兩部分內(nèi)容。
1)請求頭:包含了對客戶端的環(huán)境描述、客戶端請求信息等。
GET/minion.pngHTTP/1.1
//包含了請求方法、請求資源路徑、HTTP協(xié)議版本
Host:86:32812
//客戶端想訪問的服務(wù)器主機地址
User-Agent:Mozilla/5.0
//客戶端的類型,客戶端的軟件環(huán)境
Accept:text/html
//客戶端所能接收的數(shù)據(jù)類型
Accept-Language:zh-cn
//客戶端的語言環(huán)境
Accept-Encoding:gzip
//客戶端支持的數(shù)據(jù)壓縮格式
2)請求體:客戶端發(fā)給服務(wù)器的具體數(shù)據(jù),例如文件數(shù)據(jù)(POST請求才會有)。
同樣,一個完整的HTTP響應(yīng)中應(yīng)該包含以下兩部分內(nèi)容。
1)響應(yīng)頭:包含了對服務(wù)器的描述、對返回數(shù)據(jù)的描述。
HTTP/1.1200OK
//包含了HTTP協(xié)議版本、狀態(tài)碼、狀態(tài)英文名稱
Server:Apache-Coyote/1.1
//服務(wù)器的類型
Content-Type:image/jpeg
//返回數(shù)據(jù)的類型
Content-Length:56811
//返回數(shù)據(jù)的長度
Date:Mon,23Jun201412:54:52GMT
//響應(yīng)的時間
2)響應(yīng)體:服務(wù)器返回給客戶端的具體數(shù)據(jù),例如文件數(shù)據(jù)。
常見的響應(yīng)狀態(tài)碼如圖所示。
常見的響應(yīng)狀態(tài)碼
此外,在iOS開發(fā)中發(fā)送HTTP請求有以下幾種方案:
1)NSURLConnection。iOS7之前,通常使用NSURLConnection及關(guān)聯(lián)類,這是iOS開發(fā)中最經(jīng)典的網(wǎng)絡(luò)請求方案。
2)NSURLSession。iOS7之后,逐漸取代NSURLConnection,現(xiàn)在已經(jīng)是iOS開發(fā)中最常用的網(wǎng)絡(luò)請求方式。
3)CFNetwork。它是NSURLConnection和NSURLSession的底層C語言實現(xiàn),很少在開發(fā)中使用。
4)其他第三方網(wǎng)絡(luò)請求框架,如Objective-C中的AFNetworking和Swift中的Alamofire等。這些網(wǎng)絡(luò)框架也基本上都是對其他3種方案的封裝與拓展。
4.
iOS9以后如何使用HTTP請求?正確答案:在iOS9之后引入了新特性AppTransportSecurity(ATS)。新特性要求App內(nèi)訪問的網(wǎng)絡(luò)必須使用HTTPS協(xié)議。由于當(dāng)前很多項目仍然使用HTTP協(xié)議和私有加密協(xié)議進行網(wǎng)絡(luò)請求,所以需要在項目的info.plist文件中做如下配置:
1)在Info.plist中添加NSAppTransportSecurity類型Dictionary。
2)在NSAppTransportSecurity下添加NSAllowsArbitraryLoads類型Boolean,值設(shè)為YES。或者,如果有部分請求需要使用HTTP協(xié)議,那么可以考慮添加白名單,即NSExceptionDomains。用鼠標(biāo)右鍵單擊info.plist,選擇OpenAs選項下的SourceCode,在打開的文件中添加如下代碼,其中ExceptionDomain是需要設(shè)置的白名單域名。
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>ExceptionDomain</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
<key></key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
</dict>
5.
HTTPS協(xié)議與HTTP協(xié)議有什么區(qū)別與聯(lián)系?正確答案:HTTP協(xié)議被用于在Web瀏覽器和網(wǎng)站服務(wù)器之間傳遞信息。HTTP協(xié)議以明文方式發(fā)送內(nèi)容,不提供任何方式的數(shù)據(jù)加密,如果攻擊者截取了Web瀏覽器和網(wǎng)站服務(wù)器之間的傳輸報文,那么就可以直接讀懂其中的信息。因此,HTTP協(xié)議不適合傳輸一些敏感信息,如信用卡號、密碼等。
為了解決HTTP協(xié)議的這一缺陷,需要使用另一種協(xié)議:安全套接字層超文本傳輸協(xié)議(HTTPS)。為了數(shù)據(jù)傳輸?shù)陌踩?,HTTPS在HTTP的基礎(chǔ)上加入了SSL協(xié)議,SSL依靠證書來驗證服務(wù)器的身份,并為瀏覽器和服務(wù)器之間的通信加密。
HTTPS和HTTP的區(qū)別主要為以下4點:
1)HTTPS協(xié)議需要從CA(CertificateAuthority)申請一個用于證明服務(wù)器用途類型的證書,一般免費證書很少,需要交費。
2)HTTP是超文本傳輸協(xié)議,信息是明文傳輸,HTTPS則是具有安全性的SSL加密傳輸協(xié)議。
3)HHTP和HTTPS使用的是完全不同的連接方式,用的端口也不一樣,前者是80,后者是443。
4)HTTP的連接很簡單,是無狀態(tài)的;HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議,比HTTP協(xié)議安全。
6.
UIKit類要在哪一個應(yīng)用線程上使用?正確答案:UIKit的界面類只能在主線程上使用,對界面進行更新,多線程環(huán)境中要對界面進行更新必須要切換到主線程上。
例如下面的問題代碼:
@interfaceTTWaitController:UIViewController
@property(strong,nonatomic)UILabel*alert;
@end
@implementationTTWaitController
-(void)TiewDidLoad
{
CGRectframe=CGRectMake(20,200,200,20);
self.alert=[[UILabelalloc]initWithFrame:frame];
self.alert.text=@"Pleasewait10seconds...";
self.alert.textColor=[UIColorwhiteColor];
[self.viewaddSubview:self.aleft];
NSOperationQueue*waitQueue=[[NSOperationQueuealloc]init];
[waitQueueaddOperationWithBlock:^{
[NSThreadsleepUntilDate:[NSDatedateWithTimeIntervalSinceNow:10]];
self.alert.text=@"Thanks!";
}];
}
@end
@implementationTTAppDelegate
-(BOOL)application:(UIApplication*)application
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
self.window=[[UIWindowalloc]initWithFrame:[[UIScreenmainScreen]bounds]];
self.window.rootViewController=[[TTWaitControlleralloc]init];
[self.windowmakeKeyAndVisible];
returnYES;
}
這段代碼是想提醒用戶等待10s,10s后在標(biāo)簽上顯示“Thanks”,但多線程代碼部分NSOperationQueue的addOperationWithBlock函數(shù)不能保證block里面的語句是在主線程中運行的,UILabel顯示文字屬于UI更新,必須要在主線程進行,否則會有未知的操作,無法在界面上及時正常顯示。
解決方法是將UI更新的代碼寫在主線程上。代碼同步到主線程上主要有3種方法:NSThread、NSOperationQueue和GCD,3個層次的多線程都可以獲取主線程并同步。
7.
iOS中有哪幾種從其他線程回到主線程的方法?正確答案:iOS中只有主線程才能立即刷新UI。如果是通過偵聽異步消息,觸發(fā)回調(diào)函數(shù),或者調(diào)用異步方法,請求刷新UI,那么都會產(chǎn)生線程阻塞和延遲的問題。如果要在其他線程中執(zhí)行刷新UI的操作,那么就必須切換回主線程。主要由以下3種方式。
1.NSThreadPerformAdditions協(xié)議
這個協(xié)議提供了兩個切換到主線程的API。
-(void)performSeleetorOnMainThread:(SEL)aSelectorwithObject:
(nullableid)argwaitUntilDone:(BOOL)waitmodes:(nullableNSArray<NSString*>*)array;
-(void)performSelectorOnMainThread:(SEL)aSelectorwithObject:
(nullableid)argwaitUntilDone:(BOOL)wait;
2.GCD
使用GCD的dispatch_get_main_queue()方法可以獲取主隊列,主隊列中的任務(wù)必定是在主線程中執(zhí)行的。
dispacch_async(dispatch_get_main_queue(),^{
});
3.NSOperationQueue
和GCD一樣,使用NSOperationQueue提供+mainQueue方法可以獲取主隊列,再將刷新UI的任務(wù)添加到主隊列中。
[[NSOperationQueuemainQueue]addOperationWithBlock:^{
}];
示例代碼如下:
-(void)goToMainThread{
/*開啟子線程下載圖片*/
dispatch_async(dispatch_get_global_queue(0,0),^{
NSData*imageData=[[NSDataalloc]initWithContentsOfURL:[NSURLURLWithString:@"/pe0060886.jpg"]];
_image=[UIImageimageWithData:imageData];
/*切換到主線程顯示*/
//1.NSThread
//[selfperformSeteetorOnMainThread:@selector(changeBg)withObject:nilwaitUntilDone:NO];
//2.GCD
//dispatch_async(dispatch_get_main_queue(),^{
//[selfehangeBg];
//});
//3.NSOperationQueue
[[NSOperationQueuemainQueue]addOperationWithBlock:^{
[selfchangeBg];
}];
});
}
8.
用戶下載一個大圖片,分成很多份下載,如何使用GCD實現(xiàn)?正確答案:使用DispatchGroup追加block到GlobalGroupQueue,這些block如果全部執(zhí)行完畢,那么就會執(zhí)行通過dispatch_group_notify添加到主隊列中的block,進行圖片的合并處理。
dispatch_queue_tqueue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_group_tgroup=dispatch_group_create();
dispatch_group_async(group,queue,^{/*加載圖片1*/});
dispatch_group_async(group,queue,^{/*加載圖片2*/});
dispatch_group_async(group,queue,^{/*加載圖片3*/});
dispatch_group_notify(group,dispatch_get_main_queue(),^{
//合并圖片......
});
9.
項目中什么時候選擇使用GCD?什么時候選擇NSOperation?正確答案:下圖簡單概括了NSOperation和GCD各自的特點。NSOperation是對線程的高度抽象,提供Objective-C語言接口,具備面向?qū)ο筇匦?復(fù)用、封裝),可子類化NSOperation進行操作對象的復(fù)用,使程序邏輯結(jié)構(gòu)更清晰。比起GCD,NSOperation可以直接設(shè)置操作之間的依賴關(guān)系實現(xiàn)線程同步,而且可以通過調(diào)用cancel方法中途取消操作,而在GCD中不可取消。NSOperation的線程邏輯控制更加精細(xì)靈活,同時復(fù)雜度較GCD要高,因此建議在有特殊需求的復(fù)雜項目中使用。
NSOperation和GCD的特點
GCD的最大優(yōu)點是非常簡單、易用,經(jīng)過了官方的優(yōu)化更加安全高效(多數(shù)函數(shù)是線程安全的)。對于不復(fù)雜的多線程操作,會節(jié)省代碼量,尤其block參數(shù)的使用,使代碼更為易讀,建議在簡單項目中廣泛使用。
10.
NSOpertion如何實現(xiàn)線程依賴?正確答案:對于a、b、c3個線程,如何使用NSOpertion和NSOpertionQueue實現(xiàn)執(zhí)行完a和b后再執(zhí)行c的結(jié)果?
對于上述問題,其實可以通過NSOpertion的依賴特性實現(xiàn),即讓c依賴于a和b,這樣只有a和b都執(zhí)行完后,c才可以開始執(zhí)行。
/*獲取主隊列(主線程)*/
NSOperationQueue*queue=[NSOperationQueuemainQueue];
/*創(chuàng)建a、b、c操作*/
NSOperation*a=[NSBlockOperationblockOperationWithBlock:^{
NSLog(@"OperationAStart!");
[NSThreadsleepForTimeInterval:3.0];
NSLog(@"OperationADone!");
}];
NSOperation*b=[NSBlockOperationblockOperationWithBlock:^{
NSLog(@"OperationBStart!");
[NSThreadsleepForTimeInterval:3.0];
NSLog(@"OperationBDone!");
}];
NSOperation*C=[NSBlockOperationbloekOperationWithBlock:^{
NSLog(@"OperationCStart!");
//......
}];
/*添加操作依賴,c依賴于a和b*/
[caddDependency:a];
[caddDependency:b];
/*添加操作a、b、c到操作隊列queue(特意將c在a和b之前添加)*/
[queueaddOperation:c];
[queueaddOperation:a];
[queueaddOperation:b];
程序的輸出結(jié)果為:
2017-03-1813:51:37.770SingleView[15073:531745]OperationAStart!
2017-03-1813:51:40.772SingleView[15073:531745]OperationADone!
2017-03-1813:51:40.775SingleView[15073:531745]OperationBStart!
2017-03-1813:51:43.799SingleView[15073:531745]OperationBDone!
2017-03-1813:51:43.800SingleView[15073:5317451OperationCStart!
11.
dispatch_barrier_(a)sync的作用是什么?正確答案:通過dispatch_barrier_async添加的操作會暫時阻塞當(dāng)前隊列,即等待前面的并發(fā)操作都完成后執(zhí)行該阻塞操作,待其完成后后面的并發(fā)操作才可繼續(xù)(見圖)。可以將其比喻為一根霸道的獨木橋,是并發(fā)隊列中的一個并發(fā)障礙點,或者說中間瓶頸,臨時阻塞并獨占。注意,dispatch_barrier_async只有在并發(fā)隊列中才能起作用,在串行隊列中隊列本身就是獨木橋,將失去其意義。
dispatch_barrier_async阻塞隊列
可見使用dispatch_barrier_async可以實現(xiàn)類似dispatch_group_t組調(diào)度的效果,同時主要的作用是避免數(shù)據(jù)競爭,高效訪問數(shù)據(jù)。
/*創(chuàng)建并發(fā)隊列*/
dispatch_queue_tconcurrentQueue=dispatch_queue_create("test.concurrent.queue",DISPATCH_QUEUE_CONCURRENT);
/*添加兩個并發(fā)操作A和B,即A和B會并發(fā)執(zhí)行*/
dispatch_async(concurrentQueue,^(){
NSLog(@"OperationA");
});
dispatch_async(concurrentQueue,^(){
NSLog(@"OperationB");
});
/*添加barrier障礙操作,會等待前面的并發(fā)操作結(jié)束,并暫時阻塞后面的并發(fā)操作直到其完成*/
dispatch_barrier_async(concurrentQueue,^(){
NSLog(@"OperationBarrier!");
});
/*繼續(xù)添加并發(fā)操作C和D,要等待barrier障礙操作結(jié)束才能開始*/
dispatch_async(concurrentQueue,^(){
NSLog(@"OperationC");
});
dispatch_async(concurrentQueue,^(){
NSLog(@"OperationD");
});
程序的輸出結(jié)果為:
2017-04-0412:25:02.344SingleView[12818:3694480]OperationB
2017-04-0412:25:02.344SingleView[12818:3694482]OperationA
2017-04-0412:25:02.345SingleView[12818:3694482]OperationBarrier!
2017-04-0412:25:02.345SingleView[12818:3694482]OperationD
2017-04-0412:25:02.345SingleView[12818:3694480]OperationC
12.
如何理解線程安全?正確答案:在實際開發(fā)中,如果在程序中使用了多線程技術(shù),那么有可能會遇到同一塊資源被多個線程共享的情況,也就是多個線程可能會訪問同一塊資源,如多個線程訪問同一對象、變量、文件等。因此,當(dāng)多個線程訪問同一塊資源時,很容易會發(fā)生數(shù)據(jù)錯誤及數(shù)據(jù)不安全等問題。
要避免這種因爭奪資源而導(dǎo)致的數(shù)據(jù)安全問題,需要使用“線程鎖”來解決,即在同一時間段內(nèi),只允許一個線程來使用資源。在iOS開發(fā)中主要使用如下幾種線程鎖技術(shù)。
1.@synchronized關(guān)鍵字
使用@synchronized能夠很方便地隱式創(chuàng)建鎖對象。示例代碼如下:
-(void)testSynchronized{
Animal*someone=[Animalnew];
/*線程A*/
dispatch_async(dispatch_get_global_queue(0,0),^{
@synchronized(someone){
NSLog(@"線程A=%@",[NSThreadcurrentThread]);
=@"□";
[NSThreadsleepForTimeInterva!:5];
}
});
/*線程B*/
dispatch_async(dispatch_get_global_queue(0,0),^{
@synchronized(someone){
NSLog(@"線程B=%@",[NSThreadcurrentThread]);
=@"
";
}
});
}
程序的輸出結(jié)果為:
2017-04-1217:00:49.495test[91509:22528009]線程A=<NSThread:0x608000261a00>{number=5,name=(null)}
2017-04-1217:00:54.570test[91509:22529035]線程B=<NSThread:0x600000265840>{number=6,name=(null)}
可以發(fā)現(xiàn)線程B訪問資源的時間比線程A要晚5s。關(guān)鍵字@synchronized將實例對象someone設(shè)定為鎖的唯一標(biāo)識,只有標(biāo)識相同時,才滿足互斥。如果線程B中鎖的標(biāo)識改為其他對象,那么線程B將不會被阻塞。
2.NSLock
NSLock對象是iOS中為了保證臨界資源的原子性操作和臨界區(qū)的原子性執(zhí)行而封裝的。需要注意的是,NSLock對象中的unlock操作必須與lock操作使用相同的線程,否則會出現(xiàn)未知錯誤。此外,同一線程在lock之后,未unlock之前,再次lock會導(dǎo)致永久性死鎖。
示例代碼如下:
-(void)testNSLock{
Animal*someone=[Animalnew];
/*創(chuàng)建鎖對象*/
NSLock*alock=[[NSLockalloc]init];
/*線程A*/
dispatch_async(dispatch_get_global_queue(0,0),^{
/*嘗試上鎖*/
if([alocktryLock]){//[alocklock];
NSLog(@"線程A=%@",[NSThreadcurrentThread]);
=@"□";
[NSThreadsleepForTimeInterval:5];
/*開鎖*/
[alockunlock];
}
});
/*線程B*/
dispatch_async(dispatch_get_global_queue(0,0),^{
if([alocktryLock]){//[alocklock];
YSLog(@"線程B=%@",[NSThreadcurrentThread]);
=@"
";
[alockunlock];
}
});
}
程序的輸出結(jié)果為:
2017-04-1316:29:41.086test[15054:24437220]線程A=<NSThread:0x6000002697c0>{number=3,name=(null)}
2017-04-1316:29:46.088test[15054:24437846]線程B=<NSThread:0x600000274980>{number=4,name=(null)}
結(jié)果顯示線程B在等待線程A解鎖之后,才會執(zhí)行程序。如果線程B將lock和unlock方法去掉之后而不會被阻塞,那么這個和synchronized的一樣,需要使用相同的鎖對象才會互斥。
除了NSLock之外,iOS還提供了NSRecursiveLock類和NSConditionLock類,前者通常在遞歸操作中使用,后者可以創(chuàng)建一個指定開鎖條件的鎖對象,只有滿足條件,才能開鎖。
3.GCD
GCD提供了一種信號的機制,使用它可以創(chuàng)建鎖。信號量是一個整型值并且具有一個初始計數(shù)值,可支持兩個操作:信號通知和等待。當(dāng)一個信號量被信號通知,其計數(shù)會被增加。當(dāng)一個線程在一個信號量上等待時,線程會被阻塞(如果有必要),直至計數(shù)器大于零,然后線程會減少這個計數(shù)。
在GCD中有3個函數(shù)是semaphore的操作(見表)。semaphore操作的3個函數(shù)函數(shù)名作用dispatch_semaphore_create刨建一個semaphoredispatch_semaphore_signal發(fā)送一個信號dispatch_semaphore_wait等待信號
簡單地介紹這3個函數(shù),第一個函數(shù)有一個整型的參數(shù),可以理解為信號的總量;dispatch_semaphore_signal是發(fā)送一個信號,自然會讓信號總量加1;dispatch_semaphore_wait是等待信號,當(dāng)信號總量少于0的時候就會一直等待,否則就可以正
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年吊輪機項目可行性研究報告
- 綠色展覽環(huán)保理念在活動策劃中的實踐與探索
- 2025至2030年計量箱項目投資價值分析報告
- 跨界知識的吸收制定全面的學(xué)習(xí)計劃
- 異常處理標(biāo)準(zhǔn)化在金融科技的應(yīng)用-深度研究
- 大數(shù)據(jù)可視化工具開發(fā)-深度研究
- 2025年雙層印刷電路板項目可行性研究報告
- 果蔬批發(fā)市場發(fā)展趨勢-深度研究
- 職場學(xué)霸的職業(yè)規(guī)劃如何制定并實現(xiàn)職業(yè)目標(biāo)
- 企業(yè)文化對激勵機制影響-深度研究
- 初中班級成績分析課件
- 勞務(wù)合同樣本下載
- 聰明格練習(xí)題(初、中級)
- 韻達(dá)快遞員工勞務(wù)合同范本
- 血液透析水處理系統(tǒng)演示
- 小批量試制總結(jié)報告
- 2023年經(jīng)濟開發(fā)區(qū)工作會議表態(tài)發(fā)言
- YY/T 0216-1995制藥機械產(chǎn)品型號編制方法
- 糖尿病足與周圍血管病01課件
- 2022年試行林木采伐管理方案
- 消防設(shè)施操作員報名承諾書
評論
0/150
提交評論