에피소드 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);
}
- Chrome의 스레딩 및 Tasks
- Clang 스레드 안전 분석: 더 복잡한 시나리오를 위해 다른 Clang 주석에 관해 알아보세요.