如果在锁定相同互斥锁的另一个函数中调用,如何禁用互斥锁
How to disable mutex if called within another function locking same mutex
我有一个资源 class 由 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);
});
}
现在我无法从单个方法中删除互斥量,因为它们可以从外部批处理上下文中单独调用。我不能保留互斥锁,因为它们也可以在其中调用。如果我在 class 中保留一个布尔变量,它在 batch
函数调用中停用互斥锁,那么它也会停用从其他线程调用的其他单个函数,再次破坏目的。
一个解决方案是写下所有 read/write 函数的非互斥集,并且只在批处理上下文中调用它们,而不是在外部调用它们。但此类资源访问功能数量多,增加维护难度,可能引入BUG。
正在寻找解决此问题的替代方案。
这正是 std::recursive_mutex
的用途,它可以从同一线程多次锁定。只有当解锁调用次数与锁定调用次数匹配时才会完全解锁。
我有一个资源 class 由 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);
});
}
现在我无法从单个方法中删除互斥量,因为它们可以从外部批处理上下文中单独调用。我不能保留互斥锁,因为它们也可以在其中调用。如果我在 class 中保留一个布尔变量,它在 batch
函数调用中停用互斥锁,那么它也会停用从其他线程调用的其他单个函数,再次破坏目的。
一个解决方案是写下所有 read/write 函数的非互斥集,并且只在批处理上下文中调用它们,而不是在外部调用它们。但此类资源访问功能数量多,增加维护难度,可能引入BUG。
正在寻找解决此问题的替代方案。
这正是 std::recursive_mutex
的用途,它可以从同一线程多次锁定。只有当解锁调用次数与锁定调用次数匹配时才会完全解锁。