与自我竞争的条件

时间:2011-04-25 02:53:57

标签: c++ multithreading boost race-condition

我有一个带有成员函数的类,需要在执行操作之前在相应的互斥锁上获取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;
}

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:3)

我没有使用过增强线程,但是如果我正确读取你的代码你在主函数中锁定互斥锁,那么你调用examlpe_instance的{​​{1}}方法也试图获得一个锁在数组互斥上...自然会导致死锁,因为它看起来似乎不是重入的。

为什么要在主函数中获取锁?

更新

你不能在同一范围内重新获得两次锁,除非你有一个可重入锁(你没有),所以试着改变范围:

next()

如果boost像我想象的那样工作,那么一旦它超出范围,boost应该释放锁。尝试上面的修改,看看你是否仍然陷入僵局(如果你仍然这样做,那么你必须以某种方式明确释放锁,但我不知道在boost中是如何完成的。)

答案 1 :(得分:-1)

你想要的是recurisive_mutex,它通常被称为可重入的互斥锁。这将允许您在同一个线程中多次锁定相同的互斥锁,而不会导致死锁。因此,要修复您的示例,只需将shared_mutex的所有实例替换为recursive_mutex即可。

问题是您现在不能再使用shared_lockupgrade_to_unique_lock,因为它们都要求您拥有shared_mutex。事实证明,根据这些two links,看起来shared_mutex无论如何都是个坏主意。如果您真的需要shared_mutex,则必须编写自己的shared_recursive_mutex,因为提升不提供。{/ p>