雖然互斥量是保護共享資料最常用的手段,但卻不是唯一的。有些共享資料,只需要在初始化時保護,比如共享資料是唯讀的,在初始化之後就不用再保護了。
有些資源,在需要時才初始化:
上面函式中,在資源初始化時應該保護才對,保證多執行緒環境下,資源初始化時不被打斷。std::shared_ptrresource_ptr;
void foo()
returnce_ptr->do_something();
}
在if前面保護共享資源。在資源已經初始化的情況下,如果乙個執行緒正在執行std::unique_lock後面,lk.unlock前面**,這時再有執行緒執行的話會等待。只有在資源初始化時才需要保護,std::shared_ptrresource_ptr;
void foo()
lk.unlock();
returnce_ptr->do_something();
}
所以鎖可以加到if後面
上面**其實還有個bug。構造資源時使用了鎖,但是在使用資源時沒有使用鎖。如果資源構造時間比較久,在構造了一半時,resource_ptr已經不是null,但是還沒有構造完。這時有另外乙個執行緒來呼叫,就會出錯。std::shared_ptrresource_ptr;
void foo()
}resournce_ptr->do_something();
}
c++標準委員會已經為這種情況提供了解決的方法:使用std::once_flag和std::call_once。
有些共享資料很少更新,例如dns檔案,很可能在幾個月甚至更長一段時間都不會更新,如果每次在使用dns檔案時都加鎖,那麼效率就降低很多。我們知道,linux中有種鎖叫「讀寫鎖」(reader-wiriteer mutex),但是c++11不支援。這時可以使用boost庫中的shared_mutex。std::shared_ptrrescource_ptr;
std::once_flag rescource_flag;
void init_resource()
void foo()
如果對乙個互斥量兩次上鎖,會死鎖。但是有些時候的確需要這樣做,那麼就可以使用遞迴鎖std::recursive_mutex。它工作原理和mutex相同,但是可以給它多次上鎖,多次上鎖後要多次解鎖。#include#include#include#includeclass dns_entry;
class dns_cash
void update_or_add_entry(std::string const& domain,
dns_entry const& dns_details)
};
在大多數情況下,不需要使用遞迴鎖。如果你要使用,很可能你需要更改你的設計。在陳碩的《linux多執行緒伺服器程式設計》中有講到不建議使用遞迴鎖的原因:遞迴鎖和非遞迴鎖效能差別不大,遞迴鎖只是多了乙個計數器。使用非遞迴鎖可以讓我們在編碼時思考**對鎖的期求,及早發現問題。
C 11保護共享資料的其他方法
保護共享資料的初始化過程 在多執行緒程式設計中,互斥量是最通用的保護共享資料的機制。但是在某些情況下,一些資源僅需要在第一次初始化的時候需要保護,其時候就可以不需要互斥變數的保護了。比如編碼中最常見的單例模式,核心 如下 3 獲得本類例項的唯一全域性訪問點 static csinglton geti...
方向的選擇,資料庫?網路程式設計?其他?
還是在linux c平台上,選擇資料庫或者網路程式設計吧。先從兩者入門開始,看下自己適合哪方面,給自己半年時間去選擇,因為寶寶目前太小,等到年底就一歲半了,我就能投入更多的精力,目前還是得以小寶為主,畢竟小孩的成長沒法重來,而我的選擇還可以重新來過。哈哈,bb昨天自己推著箱子玩的很high,能自己扶...
C 學習之共享資料的保護
對於既需要共享 又需要防止改變的資料應該宣告為常型別 用const進行修飾 對於不改變物件狀態的成員函式應該宣告為常函式。1 常物件 必須進行初始化,不能被更新。const 類名 物件名 2 常成員 用const進行修飾的類成員 常資料成員和常函式成員 3 常引用 被引用的物件不能被更新。const...