文章分享至我的個人技術部落格: https://cainluo.github.io/14971830645415.html
Thread Sanitizer(TSan)
Thread Sanitizer
這個怎麼翻譯呢...其實我想了很久,執行緒洗手液
?執行緒清掃車
? 感覺都不太對....於是乎還是不翻譯了, 我們只要知道這個東西是用來解決執行緒問題的就哦了, 我這個是Objective-c
版本的, 如果你們喜歡Swift
版本的話, 可以去找找Swift版本
使用場景
那麼在什麼時候會用到這個Thread Sanitizer
呢? 其實就是在我們精心開發好一個App之後, 發現有斷斷續續不停的小Bug, 然後會導致Crash
等問題, 你又沒法找到的時候, 就可以用這個東西試試看啦.
那一般會在什麼情況下會發生呢? 我找到了一段比較官方的文字, 大家湊合著看看吧.
通常, 這些都是多個執行緒同時訪問記憶體中的同一段地址造成的。相信執行緒問題是許多開發人員的噩夢。它們難以跟蹤,因為錯誤只發生在某些條件下,所以確定問題的根本原因可能是非常棘手的。通常的原因是所謂的“race condition”。
當兩個執行緒併發訪問同一個變數,並且至少有一個訪問是寫時,會發生資料競爭。
Thread Sanitizer(TSan)可以檢查的型別錯誤
雖然說Thread Sanitizer
這個工具很牛逼, 但也不是萬能的, 它只能夠檢測出以下幾種錯誤.
- Use of uninitialized mutexes
- Thread leaks (missing phread_johin)
- Unsafe calls in signal handlers (ex:malloc)
- Unlock from wrong thread
- Data race
開啟Thread Sanitizer工具
Thread Sanitizer
工具是在工程裡的Edit Scheme
-> Diagnostics
開啟,
並不像Instruments
那樣在Developer Tools
裡開啟.
建立專案
一切所有的東西, 都要從程式碼入手, 這裡我們也是一樣, 寫一個小小的Demo
來演示演示, UI
略醜, 大家湊合著看吧....程式碼的話, 在工程裡自行去翻查吧~
裡面的佈局程式碼也沒有什麼好看的, 這裡直接用的是Masonry
, 感謝Masonry
作者的無私奉獻~~
運算邏輯
這裡我就不寫那麼大的數額了, 就取十位數哦了(別說我小氣),
這裡的存入邏輯灰常的簡單, 計算完結果之後就傳入進去:
- (void)setMoneyInTheBank {
NSString *amount = [NSString stringWithFormat:@"總額: ¥%ld", self.bankView.amount + 10];
[self.bankView changeLabelContentWithString:amount];
}
複製程式碼
本來接著要去寫取得邏輯, 但這裡想到一個情況, 快速的按存和取, 那就會發生剛剛在文章開頭所說的資料競爭問題, 這裡經過思考後, 發現要使用一丟丟多執行緒的技巧.
- (void)getMoneyOfBanek {
dispatch_async(dispatch_queue_create("com.threadsanitizer.ThreadSanitizer", nil), ^{
if (self.amount <= 0) {
NSLog(@"你都沒錢啦, 怎麼取?");
return;
}
// 這是讓執行緒先休息一秒先~
sleep(1);
dispatch_async(dispatch_get_main_queue(), ^{
NSString *amount = [NSString stringWithFormat:@"總額: ¥%ld", self.amount -= 10];
[self.bankView changeLabelContentWithString:amount];
});
});
}
複製程式碼
寫完之後, 然後執行, 狂點存和取, 然後就會出現下面醬紫的畫面:
是不是很容易就找出問題的所在呢?
原理的話, 大概就和你吃飯一樣, 先嚥下第一口再嚥下第二口, 不然一起嚥下, 就會嗆著了.
順便說說:
- TSan 是一個檢查 Runtime Issues 的工具 (不支援靜態檢查)
- 只能執行在語言版本3編寫的Swift程式碼上 (Objective-C也可相容),
- 只能在64位macOS 或 64位模擬器上執行 (所有真機裝置都不可以用來除錯)。
工程地址
專案地址: https://github.com/CainRun/iOS-10-Characteristic/tree/master/2.Thread%20Sanitizer