c++ - 为什么这段代码会产生竞争条件?

标签 c++ multithreading c++11 race-condition

这是我第一次尝试使用 std::future

我想同时解析三个不同的文件。三个功能分别做到了这一点。称为 parseSentencesparseTagsparseLinks。它们中的每一个都通过一个非常简单的 lambda 函数使用 std::async 在单独的线程中启动:[]() { parser->function(); },其中 parser 是一个静态变量,function 是我之前命名的三个函数之一。

int parser::start()
{
    int ret = SUCCESS;
    ASSERT( m_output != nullptr );
    static parser * thisParserInstance = this;

    // parsing files
    std::future<int> parseSentence = std::async(std::launch::async, []() { return thisParserInstance->parseSentences(); } );
    std::future<int> parseLinksResult = std::async(std::launch::async, []() { return thisParserInstance->parseLinks(); } );
    std::future<int> parseTagsResult = std::async(std::launch::async, []() { return thisParserInstance->parseTags(); } );

    // retrieving the results
    ret = parseSentence.get();
    const int linksResult = parseLinksResult.get();
    const int tagsResult = parseTagsResult.get();

    if (ret == SUCCESS)
        ret = linksResult == SUCCESS ? tagsResult : linksResult;

    return ret;
}

现在,当我在 gdb 中运行我的程序时,在破坏 std::future 局部变量之一时发生段错误。当时有 2 个线程在运行。 线程 #1 的调用栈是 here . 线程 #2 的调用栈是 here .

请注意,第一个调用堆栈中指向this 的指针为空,从而导致段错误。

如果有人知道,我将不胜感激。

最佳答案

这里有一个大问题:

static parser * thisParserInstance = this;

这是在您第一次调用该函数时初始化的,然后在以后的调用中保持不变。因此,如果您在一个对象上调用该函数,销毁该对象,然后在第二个对象上调用它,您实际上是在处理一个指向已失效对象的悬空指针。这肯定会产生未定义的行为。

没有理由使用静态变量; lambda 可以捕获 this 并作用于正确的对象。或者更简单地说,如评论中所建议的那样,使用可变形式的 asyncthis 绑定(bind)到成员函数:

std::async(std::launch::async, &parser::parseSentences, this);

关于c++ - 为什么这段代码会产生竞争条件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12150342/

相关文章:

iphone - Grand Central Dispatch (GCD) 与 performSelector - 需要更好的解释

c++ - 在 C++ 中使用右值设置类变量的最有效方法是什么?

c++ - 使用一个函数打印 map 和 unordered_map 对

c++ - 关于 "int const *p"和 "const int *p "

c++ - 使用 CMake 时 Emscripten 找不到全局路径

c++ - 操作 Windows 注册表

python 无法理解通过 Winsock 发送的 C++ 字符串

c++ - 线程在检查数据库时抛出错误

java - 在 web 应用程序的多线程环境中管理资源

c++ - 如何调试输出指向成员的指针?