為了實現執行緒安全性,C++ 中有兩種方法:使用互斥量保護臨界區,允許一次只有一個執行緒存取。使用原子操作,以不可分割的方式執行操作,消除了並發存取問題。
C++ 類別設計中實作執行緒安全性
引言
在多在線程環境中,保證資料的線程安全性至關重要。 C++ 中有幾種方法可以實現這一點。本文將探討如何使用互斥和原子操作來設計線程安全的類別。
互斥量
互斥量是一種鎖定機制,它允許一次只能有一個執行緒存取臨界區。當一個執行緒進入臨界區時,它會取得互斥量的所有權。其他執行緒在試圖進入臨界區時會阻塞,直到該執行緒釋放互斥。
class ThreadSafeCounter { private: std::mutex m_mutex; int m_count; public: void increment() { std::lock_guard<std::mutex> lock(m_mutex); ++m_count; } int get() { std::lock_guard<std::mutex> lock(m_mutex); return m_count; } };
在上面的範例中,increment()
和get()
方法都使用標準庫中的std::mutex
保護臨界區。當一個執行緒正在更新計數時,其他執行緒無法同時進入 increment()
方法。
原子操作
原子運算是一種特殊類型的操作,它以不可分割的方式執行。這意味著一次只能在單一執行緒中執行這些操作,從而消除了並發存取引發的問題。 C++11 中引入了 std::atomic
函式庫,它提供了原子操作的類別。
class ThreadSafeCounterAtomic { private: std::atomic<int> m_count; public: void increment() { ++m_count; } int get() { return m_count.load(); } };
在本例中,m_count
是一個原子整數,可以安全地從多個執行緒中進行增量和取得。 std::atomic<int>::load()
方法以線程安全的方式取得原子整數的值。
實戰案例
考慮一個需要從多個執行緒並行更新的共享計數器的範例:
#include <thread> int main() { std::unique_ptr<ThreadSafeCounter> counter = std::make_unique<ThreadSafeCounter>(); std::vector<std::thread> threads(10); for (auto& thread : threads) { thread = std::thread([&] { for (int i = 0; i < 1000000; ++i) { counter->increment(); } }); } for (auto& thread : threads) { thread.join(); } std::cout << "最终计数:" << counter->get() << std::endl; }
在這個程式中,我們從10個執行緒並行更新計數器,然後在主執行緒中列印最終計數。互斥量可確保計數器在任何時刻最多只能由一個執行緒更新,從而確保執行緒安全性。
結論
透過使用互斥和原子操作,可以設計執行緒安全的 C++ 類別。互斥量適用於保護需要串行存取的臨界區,而原子操作適用於無需串行存取且可以原子方式執行的操作。
以上是C++類別設計中如何實作執行緒安全性?的詳細內容。更多資訊請關注PHP中文網其他相關文章!