繁体   English   中英

c ++ 11 std :: atomic_flag,我正确使用它吗?

[英]c++ 11 std::atomic_flag, am I using this correctly?

我有一个简单的布尔值,我需要以线程安全的方式进行测试和设置。 如果一个线程已经在工作,我希望第二个线程退出。 如果我正确理解std::atomic_flag ,这应该可以正常工作。 但是,我没有信心我正确理解std::atomic_flag :)我似乎无法在线找到许多简单的例子,除了这个螺旋锁示例:

// myclass.cpp
#using <atomic>

namespace  // anonymous namespace
{
    std::atomic_flag _my_flag = ATOMIC_FLAG_INIT;
}  // ns

myclass::do_something()
{
    if ( !::_my_flag.test_and_set() ) )
    {
        // do my stuff here; handle errors and clear flag when done
        try
        {
            // do my stuff here
        }
        catch ( ... )
        {
            // handle exception
        }

        ::_my_flag.clear();  // clear my flag, we're done doing stuff
    }
    // else, we're already doing something in another thread, let's exit
}  // do_something

更新:根据以下建议更新代码,形成正确使用std::atomic_flag正确模板。 谢谢大家!

atomic_flag是一个非常低级别的构造,并不意味着广泛使用。 也就是说,我相信你的用法正如你想要的那样,除非在特殊情况下可能会清除旗帜。 如果发生了与std::exception匹配的std::exception ,则该标志不会被清除。

通常RAII应该用于此类事情。 'R'通常代表'资源',但我喜欢Jon Kalb 使用 '责任'。 设置标志后,您有责任在完成后清除标志,因此您应该使用RAII来确保履行职责。 如果在特殊情况下你需要做的所有事情都可以通过这种方式完成,那么try / catch对就会消失。

if ( !std::atomic_flag_test_and_set( &::_my_flag ) )
{
    flag_clearer x(&::_my_flag);

    // do my stuff here
}

但是您不需要自己编写flag_clearer类型。 相反,您可以简单地使用更高级别的构造,例如互斥锁和lock_guard:

namespace
{
    std::mutex my_flag;
}

myclass::do_something()
{
    if ( my_flag.try_lock() )
    {
        std::lock_guard<std::mutex> x(my_flag, std::adopt_lock);
        // do my stuff here
    }
    // else, we're already doing something in another thread, let's exit
}

是的,如果某个其他线程已经设置了标志并且没有人清除它,那将跳过if块内的代码。 如果没有其他代码与标志混淆,则意味着某个线程当前正在执行该块。

然而,原子旗是相当低的水平; 考虑使用atomic_bool 此外,由于这是C ++,您可以使用成员函数进行集合和清除。

编辑:

不, atomic_bool不容易做你想做的事。 坚持使用atomic_flag ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM