std::atomic_bool
是 C++ 標準庫中提供的一種 原子類型,用于在多線程環境下對布爾值進行 線程安全的讀寫操作,避免使用 std::mutex
帶來的性能開銷。
1. 基本作用
在多線程環境中,多個線程同時訪問一個 bool
類型變量可能會出現 競態條件(race condition)。使用 std::atomic_bool
可以確保:
- 每次讀取和寫入都是 原子性的;
- 不需要手動加鎖;
- 性能比
std::mutex
更好,適用于控制標志位等簡單變量。
2. 常用操作
操作 | 說明 |
---|---|
load() | 原子讀取值 |
store(true/false) | 原子寫入值 |
exchange(value) | 原子地將值替換為 value 并返回舊值 |
compare_exchange_weak | 原子比較并條件賦值(弱) |
compare_exchange_strong | 原子比較并條件賦值(強) |
3. 示例代碼:線程安全的停止標志
#include <iostream>
#include <thread>
#include <atomic>
#include <chrono>std::atomic_bool stop_flag(false);void worker_thread() {std::cout << "Worker thread started.\n";while (!stop_flag.load()) {std::this_thread::sleep_for(std::chrono::milliseconds(500));std::cout << "Working...\n";}std::cout << "Worker thread stopping.\n";
}int main() {std::thread t(worker_thread);std::this_thread::sleep_for(std::chrono::seconds(2));std::cout << "Main thread: stopping worker.\n";stop_flag.store(true); // 原子寫入,通知線程退出t.join();std::cout << "Main thread: done.\n";return 0;
}
4. exchange()
用法示例
std::atomic_bool flag(false);// 原子地將 flag 設置為 true,并獲取舊值
bool was_set = flag.exchange(true);
if (!was_set) {std::cout << "First time setting flag!\n";
} else {std::cout << "Flag was already set.\n";
}
5. compare_exchange_strong()
用法示例
std::atomic_bool ready(false);
bool expected = false;if (ready.compare_exchange_strong(expected, true)) {std::cout << "We changed it from false to true.\n";
} else {std::cout << "It was already true.\n";
}
compare_exchange_strong(expected, new_val)
的意思是:
- 如果當前值 ==
expected
,則原子地賦值為new_val
,并返回true
;- 否則返回
false
,且expected
被更新為當前值。
6. 和 volatile
的區別?
項目 | std::atomic | volatile |
---|---|---|
原子性保證 | ? | ? |
線程安全 | ? | ? |
用于多線程 | ? | ?(不適用) |
7. 典型應用場景
- 線程停止標志(如
kill_switch
,terminate_flag
) - 單次初始化控制(
once_flag
替代方案) - 簡單信號通信(如觸發事件)
8. 實戰應用示例
在建圖(SLAM)系統中,std::atomic_bool
通常用于 線程控制標志,以線程安全方式實現異步邏輯的終止、控制或狀態指示。以下是詳細用途、使用示例,以及與建圖模塊結合的典型場景。
建圖系統中常見使用場景
變量名 | 類型 | 作用說明 |
---|---|---|
kill_switch | std::atomic_bool | 強制立即終止后端建圖線程 |
end_of_sequence | std::atomic_bool | 等待數據隊列處理完后自動終止線程 |
request_to_optimize | std::atomic_bool | 請求觸發一次后端優化 |
request_to_recover | std::atomic_bool | 請求重新恢復全局狀態或軌跡 |
is_mapping | std::atomic_bool | 指示建圖線程當前是否運行中 |
has_new_data | std::atomic_bool | 用于觸發新數據到來時的條件變量喚醒 |
建圖線程中的使用示例
class AsyncMapping {
public:AsyncMapping() : kill_switch(false), end_of_sequence(false), request_to_optimize(false) {mapping_thread = std::thread(&AsyncMapping::run, this);}~AsyncMapping() {kill_switch.store(true); // 強制中斷condition.notify_all();if (mapping_thread.joinable()) mapping_thread.join();}void insert_submap(const SubMap::Ptr& submap) {{std::lock_guard<std::mutex> lock(queue_mutex);submap_queue.push(submap);}request_to_optimize.store(true);condition.notify_one(); // 喚醒線程}private:void run() {while (!kill_switch.load()) {std::unique_lock<std::mutex> lock(queue_mutex);condition.wait(lock, [&]() {return kill_switch.load() || !submap_queue.empty() || request_to_optimize.load();});if (kill_switch.load()) break;// 處理隊列while (!submap_queue.empty()) {auto submap = submap_queue.front();submap_queue.pop();process_submap(submap);}if (request_to_optimize.exchange(false)) {optimize(); // 執行一次后端優化}}}void process_submap(const SubMap::Ptr& submap);void optimize();private:std::atomic_bool kill_switch;std::atomic_bool end_of_sequence;std::atomic_bool request_to_optimize;std::queue<SubMap::Ptr> submap_queue;std::mutex queue_mutex;std::condition_variable condition;std::thread mapping_thread;
};
** 技巧說明**
atomic_bool + condition_variable
是建圖線程中典型的等待-通知機制組合。exchange(false)
常用于“消費型”標志,即只觸發一次(如request_to_optimize
)。- 在析構時使用
kill_switch
可以 無鎖安全終止線程,無需強行detach
。
推薦命名規范
標志變量 | 推薦用途 |
---|---|
kill_switch | 強制立即終止所有建圖處理 |
optimization_flag | 表示優化請求 |
data_ready | 數據隊列中是否有數據可處理 |
map_updated | 是否生成新地圖輸出 |
need_save | 是否需要保存地圖(外部觸發) |
如果使用 ThreadPool
+ std::future
,也可以這樣結合:
if (request_to_optimize.exchange(false)) {thread_pool.submit([this]() {global_mapping->optimize(); // 異步觸發建圖優化});
}