与自我的竞争条件
我有一个带有成员函数的类,需要在执行操作之前在相应的互斥锁上获取 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;
}
我该如何解决这个问题?
I have a class with member functions that require a boost::unique_lock be acquired on the respective mutex before performing their operation.
However, when the member function is called when there is an existing boost::unique_lock it deadlocks itself.
#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;
}
How can I fix this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我没有使用boost线程,但是如果我正确地阅读了你的代码,你会在主函数中锁定互斥锁,然后你调用
examlpe_instance
的next()
方法,该方法也尝试获取数组互斥锁上的锁...这自然会导致死锁,因为锁似乎不是可重入的。为什么要在main函数中获取锁?
更新:
你不能在同一范围内重新获取锁两次,除非你有一个可重入锁(你没有),所以尝试改变范围:
如果 boost 像我想象的那样工作,那么 boost一旦超出范围就应该释放锁。尝试上述修改,看看是否仍然出现死锁(如果仍然出现,那么您必须以某种方式显式释放锁,但我不知道在 boost 中是如何完成的)。
I haven't used boost threading, but if I read your code correctly you lock the mutex in your main function then you call the
examlpe_instance
'snext()
method which also tries to obtain a lock on the array mutex... naturally that would cause a deadlock, since it doesn't seem like the lock is re-entrant.Why are you acquiring the lock in the main function?
Update:
You can't re-acquire a lock twice within the same scope, unless you have a re-entrant lock (which you don't), so try changing the scope:
If boost works like I imagine it should, then boost should release the lock once it gets out of scope. Try the above modification and see if you still get a deadlock (if you still do, then you have to explicitly release the lock somehow, but I don't know how that's done in boost).
你想要的是
recurisive_mutex
通常称为可重入互斥体。这将允许您在同一线程内多次锁定同一互斥锁,而不会导致死锁。因此,要修复您的示例,只需将shared_mutex
的所有实例替换为recursive_mutex
即可。问题是您现在不能再使用
shared_lock
和upgrade_to_unique_lock
因为它们都要求您有shared_mutex
。事实证明,根据这些两个链接 看起来shared_mutex
无论如何都是一个坏主意。如果您确实需要shared_mutex
,则必须编写自己的shared_recursive_mutex
,因为boost 不提供此功能。What you want is a
recurisive_mutex
which is more commonly known as a re-entrant mutex. This will allow you to lock the same mutex multiple times within the same thread without causing deadlocks. So to fix your example, just replace all instances ofshared_mutex
byrecursive_mutex
and it will work.The problem is that you can now no longer use
shared_lock
andupgrade_to_unique_lock
since they both require that you have ashared_mutex
. As it turns out, according to these two links it looks likeshared_mutex
are a bad idea anyway. If you really needshared_mutex
, you'll have to write your ownshared_recursive_mutex
because boost doesn't provide one.