Chromium Chronicle #25:Thread 安全性註解

第 25 集:由 Victor Costan 於 SFO (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);
}