iOS程序員面試分類模擬12_第1頁
iOS程序員面試分類模擬12_第2頁
iOS程序員面試分類模擬12_第3頁
iOS程序員面試分類模擬12_第4頁
iOS程序員面試分類模擬12_第5頁
已閱讀5頁,還剩11頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論