騰訊三面問題:
- OC你了解的鎖有哪些?在你回答基礎(chǔ)上進(jìn)行二次提問;
追問一:自旋和互斥對比?
追問二:用C/OC/C++,任選其一冗懦,實(shí)現(xiàn)自旋或互斥?又述即可! - 內(nèi)存泄漏可能會出現(xiàn)的幾種原因谬运,聊聊你的看法?
追問一:非OC對象如何處理?
追問二:若常用框架出現(xiàn)內(nèi)存泄漏如何處理? - 容錯(cuò)處理你們一般是注意哪些?
- 項(xiàng)目開始容錯(cuò)處理沒做?如何防止攔截潛在的崩潰?
答案
1. OC你了解的鎖有哪些?在你回答基礎(chǔ)上進(jìn)行二次提問;
-
什么是鎖?
- 在計(jì)算機(jī)科學(xué)中隙赁,鎖是一種同步機(jī)制,用于在存在多線程的環(huán)境中實(shí)施對資源的訪問限制梆暖。 你可以理解成它用于排除并發(fā)的一種策略!
- 在iOS中伞访,鎖分為遞歸鎖、條件鎖轰驳、分布式鎖厚掷、一般鎖(根據(jù)NSLock類里面的分類進(jìn)行劃分)。
常用的有以下幾種:
1.@synchronized 關(guān)鍵字加鎖
2. NSLock 對象鎖
3. NSCondition
4. NSConditionLock 條件鎖
5. NSRecursiveLock 遞歸鎖
6. pthread_mutex 互斥鎖(C語言)
7. dispatch_semaphore 信號量實(shí)現(xiàn)加鎖(GCD)
8. OSSpinLock
9.pthread_rwlock
10.POSIX Conditions
11.os_unfair_lock
3. 自旋鎖和互斥鎖
- 相同點(diǎn):都能保證同一時(shí)間只有一個(gè)線程訪問共享資源级解。都能保證線程安全冒黑。
- 不同點(diǎn):
- 互斥鎖:如果共享數(shù)據(jù)已經(jīng)有其他線程加鎖了,線程會進(jìn)入休眠狀態(tài)等待鎖勤哗。一旦被訪問的資源被解鎖抡爹,則等待資源的線程會被喚醒。
- 自旋鎖:如果共享數(shù)據(jù)已經(jīng)有其他線程加鎖了芒划,線程會以死循環(huán)的方式等待鎖冬竟,一旦被訪問的資源被解鎖欧穴,則等待資源的線程會立即執(zhí)行。
自旋鎖的效率高于互斥鎖诱咏。
使用自旋鎖時(shí)要注意:
由于自旋時(shí)不釋放CPU苔可,因而持有自旋鎖的線程應(yīng)該盡快釋放自旋鎖,否則等待該自旋鎖的 線程會一直在哪里自旋袋狞,這就會浪費(fèi)CPU時(shí)間焚辅。
持有自旋鎖的線程在sleep之前應(yīng)該釋放自旋鎖以便其他可以獲得該自旋鎖。內(nèi)核編程中苟鸯,如果持有自旋鎖的代碼sleep了就可能導(dǎo)致整個(gè)系統(tǒng)掛起同蜻。
使用任何鎖都需要消耗系統(tǒng)資源(內(nèi)存資源和CPU時(shí)間)谬泌,這種資源消耗可以分為兩類:
- 建立鎖所需要的資源
- 當(dāng)線程被阻塞時(shí)所需要的資源
追問二: 用C/OC/C++基茵,任選其一途蒋,實(shí)現(xiàn)自旋或互斥?又述即可!
cpp實(shí)現(xiàn):
//自旋鎖的實(shí)現(xiàn)
#include<atomic>
class spin_lock{
private:
std:: atomic<bool> gitartos = ATOMIC_VAR_INIT(false);
public:
spin_lock() = default;
spin_lock(const spin_lock&)=delete ;
spin_lock& operator = (const spin_lock) = delete ;
void lock(){
bool gitexpected = false;
while (!gitartos.compare_exchange_strong(gitexpected,true)) {
gitexpected = false;
}
}
void unlock(){
gitartos.store(false);
}
};
兩種鎖的加鎖原理:
- 互斥鎖:線程會從sleep(加鎖)——>running(解鎖)枯怖,過程中有上下文的切換,cpu的搶占课蔬,信號的發(fā)送等開銷何暇。
- 自旋鎖:線程一直是running(加鎖——>解鎖)句柠,死循環(huán)檢測鎖的標(biāo)志位咸包,機(jī)制不復(fù)雜桃序。
2. 內(nèi)存泄漏可能會出現(xiàn)的幾種原因,聊聊你的看法?
第一種可能:第三方框架不當(dāng)使用;
第二種可能:block循環(huán)引用;
第三種可能:delegate循環(huán)引用;
第四種可能:NSTimer循環(huán)引用
第五種可能:非OC對象內(nèi)存處理
第六種可能:地圖類處理
第七種可能:大次數(shù)循環(huán)內(nèi)存暴漲
追問一:非OC對象如何處理?
非OC對象烂瘫,其需要手動執(zhí)行釋放操作例:CGImageRelease(ref)媒熊,否則會造成大量的內(nèi)存泄漏導(dǎo)致程序崩潰。 其他的對于CoreFoundation框架下的某些對象或變量需要手動釋放坟比、C語言代碼中的malloc等需要對應(yīng)free芦鳍。
追問二:地圖類內(nèi)存若泄漏,如何處理?
地圖是比較耗費(fèi)App內(nèi)存的葛账,因此在根據(jù)文檔實(shí)現(xiàn)某地圖相關(guān)功能的同時(shí)柠衅,需要注意內(nèi)存的正確釋放,大體需要注意的有
需在使用完畢時(shí)將地圖注竿、代理等滯空為nil;
注意地圖中標(biāo)注(大頭針)的復(fù)用茄茁,并且在使用完畢時(shí)清空標(biāo)注數(shù)組等。
3.容錯(cuò)處理你們一般是注意哪些?
在團(tuán)隊(duì)協(xié)作開發(fā)當(dāng)中巩割,由于每個(gè)團(tuán)隊(duì)成員的水平不一,很難控制代碼的質(zhì)量付燥,保證代碼的健壯性宣谈,經(jīng)常會發(fā)生由于后臺返回異常數(shù)據(jù)造成app崩潰閃退的情況,為了避免這樣的情況項(xiàng)目中做一些容錯(cuò)處理键科,顯得格外重要闻丑,極大程度上降低了因?yàn)閿?shù)據(jù)容錯(cuò)不到位產(chǎn)生崩潰閃退的概率漩怎。
例如: 1.字典 2.數(shù)組; 3.野指針; 4.NSNull等~
4.如果項(xiàng)目開始容錯(cuò)處理沒做?如何防止攔截潛在的崩潰?
例:
- category給類添加方法用來替換掉原本存在潛在崩潰的方法。
- 利用runtime方法交換技術(shù)嗦嗡,將系統(tǒng)方法替換成類添加的新方法勋锤。
- 利用異常的捕獲來防止程序的崩潰,并且進(jìn)行相應(yīng)的處理侥祭。
總結(jié):
- 不要過分相信服務(wù)器返回的數(shù)據(jù)會永遠(yuǎn)的正確叁执。
- 在對數(shù)據(jù)處理上,要進(jìn)行容錯(cuò)處理矮冬,進(jìn)行相應(yīng)判斷之后再處理數(shù)據(jù)谈宛,這是一個(gè)良好的編程習(xí)慣。
虎牙--最新iOS面試題總結(jié)
一面
項(xiàng)目架構(gòu)胎署,項(xiàng)目是自己寫的嗎
fps是怎么計(jì)算的
除了用cadisplay吆录,還有什么方法嗎
kvo怎么實(shí)現(xiàn)
leaks怎么實(shí)現(xiàn)
如何代碼實(shí)現(xiàn)監(jiān)聽僵尸對象
imageWithName什么時(shí)候發(fā)生編解碼,在什么線程
isa指針里面有什么
消息發(fā)送和消息轉(zhuǎn)發(fā)流程
函數(shù)里面的參數(shù)怎么存儲
oc一個(gè)空函數(shù)里面有參數(shù)嗎
他們存在棧還是寄存器
紅黑樹等查找時(shí)間復(fù)雜度
nsdictionary的實(shí)現(xiàn)
iOS的各種鎖
如何實(shí)現(xiàn)dispatch once琼牧,要考慮什么問題
同一線程里面使用兩個(gè)@synconize會怎么樣恢筝,是遞歸鎖還是非遞歸鎖
如何增加按鈕點(diǎn)擊范圍
二面
說一下ARC
autoreleasepool可以用來干嘛
里面的對象什么時(shí)候釋放,是出來就釋放嗎
消息轉(zhuǎn)發(fā)可以用來干什么
runloop是干什么巨坊,你用來干什么了
說一下c++多態(tài)和虛函數(shù)表
TCP如何保證數(shù)據(jù)傳輸完整性
TCP為什么三次握手
http和https撬槽,全程都是非對稱加密嗎
開放性問題,很多亂序數(shù)據(jù)過來抱究,你要怎么考慮排序方法的設(shè)計(jì)
對RxSwift的看法恢氯,有用過嗎?
三面
iOS對象指針大小
對象分配到堆還是棧
http怎么區(qū)分header和body
多線程可以訪問同一個(gè)對象嗎鼓寺,多進(jìn)程呢
視頻pts和dts
視頻丟幀丟哪個(gè)好點(diǎn)
iOS各種鎖的性能勋拟,瑣是毫秒級別還是微妙級別
http請求是異步還是同步
怎么看待rn和flutter
----答案自己找吧,天兒太熱妈候。