我有一個由 a 保護的資源類std::mutex,其中任何訪問它的方法都必須被鎖定并且只能由單個執行緒執行。如果單獨呼叫各個方法,這很好用,但現在我需要將這些方法批處理在一起。在這種情況下,互斥鎖只需要鎖定一次,并且這些方法不能再次鎖定該互斥鎖(否則將陷入死鎖)。
class Resource {
mutable std::mutex mtx;
int value = 10;
void handleOpStart() const {/* Activate batch mode */ std::cout << "HandleOp activate!"<< std::endl; }
void handleOpEnd() const {/* Deactivate batch mode */ std::cout << "HandleOp deactivate!"<< std::endl; }
public:
int read() const {
std::lock_guard<std::mutex> lock(mtx);
handleOpStart(); auto result = value 10; handleOpEnd();
return result;
}
void write(int val) {
std::lock_guard<std::mutex> lock(mtx);
handleOpStart(); value = val; handleOpEnd();
}
template<typename Fn>
void batch(Fn fn) {
std::lock_guard<std::mutex> lock(mtx);
handleOpStart();
fn();
handleOpEnd();
}
void print() const {
std::lock_guard<std::mutex> lock(mtx);
std::cout << "Value: " << value << std::endl;
}
};
int main() {
Resource r;
r.print();
r.write(r.read());
r.print();
r.batch([&] {
// will cause deadlock
auto someVal = r.read();
auto someOtherVal = 10 someVal;
r.write(r.read() someOtherVal);
});
}
現在我不能從單個方法中洗掉互斥鎖,因為它們可以從外部批處理背景關系中單獨呼叫。我不能保留互斥鎖,因為它們也可以在其中呼叫。如果我在類中保留一個布爾變數,該變數在batch函式呼叫上停用互斥鎖,那么它也會停用從其他執行緒呼叫的其他單個函式,再次破壞了目的。
一種解決方案是寫下所有讀/寫函式的非互斥集,并且只在批處理背景關系中呼叫它們,而不是在外部呼叫它們。但是此類資源訪問功能的數量很大,因此增加了維護并可能引入錯誤。
尋找替代方案來解決這個問題。
uj5u.com熱心網友回復:
這正是std::recursive_mutex它的用途,它可以從同一個執行緒多次鎖定。只有當解鎖呼叫的數量與鎖定呼叫的數量匹配時,它才會完全解鎖。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/485007.html
上一篇:決議資料到資料庫時連接EADDRINUSE18.62.228.13:443
下一篇:是假用堆記憶體共享案例嗎?
