我有一个带有成员函数的类,需要在执行操作之前在相应的互斥锁上获取boost :: unique_lock。 但是,当存在boost :: unique_lock时调用成员函数时,它会自行死锁。
#include <iostream>
#include "boost/thread.hpp"
#include "boost/foreach.hpp"
#include <list>
class example {
private:
std::list< int > int_array;
std::list< int >::iterator array_iterator;
mutable boost::shared_mutex array_mutex;
public:
/*
* Move the iterator forward.
*/
inline example & next( ) {
boost::unique_lock< boost::shared_mutex > lock( array_mutex );
array_iterator++;
if( array_iterator == int_array.end( ) ) {
array_iterator = int_array.begin( );
}
return *this;
}
/*
* Get int_array_mutex.
*/
inline boost::shared_mutex & mutex( ) const {
return array_mutex;
}
/*
* Get int_array.
*/
inline std::list< int > & array() {
return int_array;
}
};
int main() {
example example_instance;
boost::unique_lock< boost::shared_mutex> lock(example_instance.mutex());
//Manipulate int_array...
example_instance.array().push_back(1);
example_instance.array().push_back(2);
example_instance.array().push_back(3);
example_instance.array().push_back(4);
BOOST_FOREACH(int & x, example_instance.array()) {
x++;
}
//Causes deadlock
example_instance.next();
std::cout << "This shall not be emitted." << std::endl;
return 0;
}
我该如何解决这个问题?
答案 0 :(得分:3)
我没有使用过增强线程,但是如果我正确读取你的代码你在主函数中锁定互斥锁,那么你调用examlpe_instance
的{{1}}方法也试图获得一个锁在数组互斥上...自然会导致死锁,因为它看起来似乎不是重入的。
为什么要在主函数中获取锁?
你不能在同一范围内重新获得两次锁,除非你有一个可重入锁(你没有),所以试着改变范围:
next()
如果boost像我想象的那样工作,那么一旦它超出范围,boost应该释放锁。尝试上面的修改,看看你是否仍然陷入僵局(如果你仍然这样做,那么你必须以某种方式明确释放锁,但我不知道在boost中是如何完成的。)
答案 1 :(得分:-1)
你想要的是recurisive_mutex
,它通常被称为可重入的互斥锁。这将允许您在同一个线程中多次锁定相同的互斥锁,而不会导致死锁。因此,要修复您的示例,只需将shared_mutex
的所有实例替换为recursive_mutex
即可。
问题是您现在不能再使用shared_lock
和upgrade_to_unique_lock
,因为它们都要求您拥有shared_mutex
。事实证明,根据这些two links,看起来shared_mutex
无论如何都是个坏主意。如果您真的需要shared_mutex
,则必须编写自己的shared_recursive_mutex
,因为提升不提供。{/ p>