与自我的竞争条件

发布于 2024-11-03 01:33:22 字数 1568 浏览 0 评论 0原文

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

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

醉南桥 2024-11-10 01:33:22

我没有使用boost线程,但是如果我正确地阅读了你的代码,你会在主函数中锁定互斥锁,然后你调用examlpe_instancenext()方法,该方法也尝试获取数组互斥锁上的锁...这自然会导致死锁,因为锁似乎不是可重入的。

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

更新:

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

int main() {
    example example_instance;

    {// new scope
        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++;
        }
    }// end scope

    // should not cause deadlock now
    example_instance.next();

    std::cout << "This shall not be emitted." << std::endl;

    return 0;
}

如果 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's next() 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:

int main() {
    example example_instance;

    {// new scope
        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++;
        }
    }// end scope

    // should not cause deadlock now
    example_instance.next();

    std::cout << "This shall not be emitted." << std::endl;

    return 0;
}

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).

嘿嘿嘿 2024-11-10 01:33:22

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

问题是您现在不能再使用 shared_lockupgrade_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 of shared_mutex by recursive_mutex and it will work.

The problem is that you can now no longer use shared_lock and upgrade_to_unique_lock since they both require that you have a shared_mutex. As it turns out, according to these two links it looks like shared_mutex are a bad idea anyway. If you really need shared_mutex, you'll have to write your own shared_recursive_mutex because boost doesn't provide one.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文