第 25 集:作者為 SFO 的 Victor Costan (2021 年 10 月)
上一集
在 C++ 中,要解決資料競爭的可能性,重點在於針對每個資料成員存取權,提供小型的執行緒安全正確性證明。 這些證明加深了大量的心理作業,特別是在審查或重構程式碼時。 Clang 的靜態分析架構接管執行緒安全證明的手動作業。
將 GUARDED_BY_CONTEXT()
新增至執行緒不安全的資料成員
大多數 Chrome 類別都不符合執行緒安全規定,因此應以單一序列使用。 為並非執行緒安全的資料成員新增註解。 不必要的註解可以安全,但缺少註解可能會造成資料競爭。
#include "base/sequence_checker.h" // for SEQUENCE_CHECKER()
#include "base/thread_annotations.h" // for GUARDED_BY_CONTEXT()
class Cache {
// Methods here.
private:
SEQUENCE_CHECKER(sequence_checker_);
base::flat_map<std::string, std::string> data_ GUARDED_BY_CONTEXT(sequence_checker_);
};
Clang 會強制執行序列檢查
如要為資料成員加上註解
Clang 可確保存取資料的方法會先執行序列安全檢查,再進行這項作業。
隨著程式碼在重構中移動
Clang 會持續強制執行 GUARDED_BY_CONTEXT()
註解。
void Cache::Set(base::StringPiece key, base::StringPiece value) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Clang warns without this.
data_.emplace(key, value);
}
在使用互斥鎖的執行緒安全類別中,將 GUARDED_BY()
新增至資料成員
為維護執行緒安全,Chrome 中的部分課程必須使用鎖定功能。 在這些情況下,請為不符合執行緒安全狀態的所有資料成員加上註解。 每個註解都指向一個在存取資料成員時必須保留的互斥鎖。
#include "base/thread_annotations.h" // for GUARDED_BY()
class ThreadSafeCache {
// Methods here.
private:
base::Lock lock_;
base::flat_map<std::string, std::string> data_ GUARDED_BY(lock_);
};
Clang 強制要求鎖定收購
請稍候,讓編譯器確保每個 base::AutoLock
的範圍正確,
以及鎖定 Acquire()
和 Release()
的通話已正確配對。
void ThreadSafeCache::Set(base::StringPiece key, base::StringPiece value) {
base::AutoLock auto_lock(lock_); // Clang warns without this.
data_.emplace(key, value);
}
- Chrome 的執行緒和工作
- Clang 執行緒安全性分析:瞭解其他 Clang 註解,適用於較複雜的情境。