玩轉iOS開發:iOS 10 新特性《Thread Sanitizer》

CainLuo發表於2017-06-13

文章分享至我的個人技術部落格: 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裡開啟.

1


建立專案

一切所有的東西, 都要從程式碼入手, 這裡我們也是一樣, 寫一個小小的Demo來演示演示, UI略醜, 大家湊合著看吧....程式碼的話, 在工程裡自行去翻查吧~

2

裡面的佈局程式碼也沒有什麼好看的, 這裡直接用的是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];
        });
    });
}
複製程式碼

寫完之後, 然後執行, 狂點存和取, 然後就會出現下面醬紫的畫面:

3

是不是很容易就找出問題的所在呢?

原理的話, 大概就和你吃飯一樣, 先嚥下第一口再嚥下第二口, 不然一起嚥下, 就會嗆著了.

順便說說:

  • TSan 是一個檢查 Runtime Issues 的工具 (不支援靜態檢查)
  • 只能執行在語言版本3編寫的Swift程式碼上 (Objective-C也可相容),
  • 只能在64位macOS 或 64位模擬器上執行 (所有真機裝置都不可以用來除錯)。

工程地址

專案地址: https://github.com/CainRun/iOS-10-Characteristic/tree/master/2.Thread%20Sanitizer


最後

碼字很費腦, 看官賞點飯錢可好

微信

支付寶

相關文章