Chromium Chronicle #25:Thread 安全性註解

第 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);
}