六、系統地避免各種指標錯誤
七、shared_ptr 技術與陷阱
八、小結
當乙個物件能被多個執行緒同時看到時,那麼物件的銷毀時機就會變得模糊不清,可能出現多種競態條件(race condition):
解決這些race condition是 c++ 多執行緒程式設計面臨的基本問題。本文試圖以shared_ptr一勞永逸地解決這些問題。
【執行緒安全的定義】:
乙個執行緒安全的 class 應當滿足以下三個條件:
物件構造要做到執行緒安全,唯一的要求是在構造期間不要洩露 this 指標,即:
// 不要這麼做( don't do this.)
class
foo:
public observer
virtual
void
update()
;};// 物件構造的正確方法:
// 要這麼做(do this)
class
foo:
public observer};
foo* pfoo =
new foo;
observable* s =
getsubject()
;pfoo-
>
observe
(s);
// 二段式構造,或者直接寫 s->register_(pfoo);
mutex 只能保證函式乙個接乙個地執行,考慮下面的**,它試圖用互斥鎖來保護析構函式:(注意**中的 (1) 和 (2) 兩處標記。)
儘管執行緒 a 在銷毀物件之後把指標置為了 null,儘管執行緒 b 在呼叫 x 的成員函式之前檢查了指標 x 的值,但還是無法避免一種 race condition:
假如執行緒a通過p1將object物件銷毀了,這時候p2就變成了野指標或者叫空懸指標,這是一種典型的記憶體錯誤:
shared_ptr是引用計數型智慧型指標,當引用計數變為0時,物件被銷毀。weak_ptr(主要是解決shared_ptr迴圈引用的問題,將其中乙個shared_ptr換成weak_ptr即可)也是引用計數型智慧型指標,但是它不增加物件的引用次數,即弱引用。
雖然我們借 shared_ptr 來實現執行緒安全的物件釋放,但是 shared_ptr 本身不是100% 執行緒安全的。它的引用計數本身是安全且無鎖的,但物件的讀寫則不是,因為shared_ptr 有兩個資料成員,讀寫操作不能原子化。根據文件 11,shared_ptr 的執行緒安全級別和內建型別、標準庫容器、 std::string 一樣,即:
請注意,以上是 shared_ptr 物件本身的執行緒安全級別,不是它管理的物件的執行緒安全級別。
執行緒安全的物件生命期管理
1.當析構函式遇到多執行緒 在即將析構乙個物件時,別的執行緒是否正在執行該物件的成員函式?如何保證在執行成員函式期間,物件不在另乙個執行緒被析構?在呼叫某個成員函式之前,如何確保物件還活著?析構函式會不會執行到一半?1.1執行緒安全類 多個執行緒同時訪問,表現出正確的行為 無論作業系統如何排程這些執...
執行緒安全的物件生命期管理(三)
c 裡可能出現的記憶體問題大致有這麼幾個方面 1 緩衝區溢位 2 空懸指標 野指標 3 重複釋放 4 記憶體洩漏 5 不配對的new delete 6 記憶體碎片 正確使用智慧型指標能很容易地解決前面5個問題。1 緩衝區溢位 用vector string或自己編寫buffer class來管理緩衝區...
執行緒安全的物件生命期管理(七)
物件池 舉例 class stockfactory boost noncopyable 這段 中有乙個問題,stock物件永遠不會被銷毀,因為map裡存的是shared ptr,那就改為weak ptr class stockfactory boost noncopyable shared ptrs...