文章分享至個人我的技術博客: https://cainluo.github.io/14971830645415.htmlhtml
Thread Sanitizer
這個怎麼翻譯呢...其實我想了好久,線程洗手液
?線程清掃車
? 感受都不太對....因而乎仍是不翻譯了, 咱們只要知道這個東西是用來解決線程問題的就哦了, 我這個是Objective-c
版本的, 若是大家喜歡Swift
版本的話, 能夠去找找Swift版本git
那麼在何時會用到這個Thread Sanitizer
呢? 其實就是在咱們精心開發好一個App以後, 發現有斷斷續續不停的小Bug, 而後會致使Crash
等問題, 你又無法找到的時候, 就能夠用這個東西試試看啦.github
那通常會在什麼狀況下會發生呢? 我找到了一段比較官方的文字, 你們湊合着看看吧.微信
一般, 這些都是多個線程同時訪問內存中的同一段地址形成的。相信線程問題是許多開發人員的噩夢。它們難以跟蹤,由於錯誤只發生在某些條件下,因此肯定問題的根本緣由多是很是棘手的。一般的緣由是所謂的「race condition」。多線程
當兩個線程併發訪問同一個變量,而且至少有一個訪問是寫時,會發生數據競爭。併發
雖說Thread Sanitizer
這個工具很牛逼, 但也不是萬能的, 它只可以檢測出如下幾種錯誤.async
Thread Sanitizer
工具是在工程裏的Edit Scheme
-> Diagnostics
打開, 並不像Instruments
那樣在Developer Tools
裏打開.工具
一切全部的東西, 都要從代碼入手, 這裏咱們也是同樣, 寫一個小小的Demo
來演示演示, UI
略醜, 你們湊合着看吧....代碼的話, 在工程裏自行去翻查吧~佈局
裏面的佈局代碼也沒有什麼好看的, 這裏直接用的是Masonry
, 感謝Masonry
做者的無私奉獻~~ui
這裏我就不寫那麼大的數額了, 就取十位數哦了(別說我小氣),
這裏的存入邏輯灰常的簡單, 計算完結果以後就傳入進去:
- (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];
});
});
}
複製代碼
寫完以後, 而後運行, 狂點存和取, 而後就會出現下面醬紫的畫面:
是否是很容易就找出問題的所在呢?
原理的話, 大概就和你吃飯同樣, 先嚥下第一口再嚥下第二口, 否則一塊兒嚥下, 就會嗆着了.
順便說說:
項目地址: https://github.com/CainRun/iOS-10-Characteristic/tree/master/2.Thread%20Sanitizer