c++ - 如何取消 std::async 函数?

标签 c++ multithreading c++11 crash stdasync

<分区>

Possible Duplicate:
Is there a way to cancel/detach a future in C++11?

有一个使用 std::futurestd::async 异步运行的成员函数。在某些情况下,我需要取消它。 (该函数连续加载附近的对象,有时对象在加载时会超出范围。)我已经阅读了 this question 的答案。解决了同样的问题,但我无法让它工作。

这是与我的实际程序具有相同结构的简化代码。在异步运行时调用 Start()Kill() 会因 input 的访问冲突而导致崩溃。

在我看来,代码应该按如下方式工作。当调用 Kill() 时,运行标志被禁用。下一个命令 get() 应该等待线程结束,它很快就会这样做,因为它会检查运行标志。线程取消后,input指针被删除。

#include <vector>
#include <future>
using namespace std;

class Class
{
    future<void> task;
    bool running;
    int *input;
    vector<int> output;

    void Function()
    {
        for(int i = 0; i < *input; ++i)
        {
            if(!running) return;
            output.push_back(i);
        }
    }

    void Start()
    {
        input = new int(42534);
        running = true;
        task = async(launch::async, &Class::Function, this);
    }

    void Kill()
    {
        running = false;
        task.get();
        delete input;
    }
};

线程似乎没有注意到将运行标志切换为 false。我的错误是什么?

最佳答案

由于没有人实际回答问题,但我会这样做。

写入和读取 running变量不是原子操作,因此代码中没有任何内容会导致两个线程之间发生任何同步,因此无法确保异步线程看到变量已更改。

一种可能发生的方式是编译器分析 Function 的代码, 确定永远不会对该线程中的变量进行任何写入,并且由于它不是原子对象,其他线程写入的内容不需要可见,因此将代码重新排列为这样是完全合法的:

void Function()
{
    if(!running) return;
    for(int i = 0; i < *input; ++i)
    {
        output.push_back(i);
    }
}

显然在这段代码中如果 running函数启动后发生变化,不会导致循环停止。

C++ 标准允许您通过两种方式同步两个线程,一种是使用互斥体,并且只读或写 running。在互斥锁被锁定时删除变量,或者使变量成为原子变量。在您的情况下,更改 running来自 boolatomic<bool>将确保对变量的写入与从中读取同步,异步线程将终止。

关于c++ - 如何取消 std::async 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14304299/

相关文章:

c++ - 多线程应用程序中的独立日志记录

java - 我的计时器线程可能用 Thread.sleep 欺骗他?

c++ - 我可以继承 C++11 中的构造函数并初始化一些额外的东西而不必重写构造函数吗?

c++ - 字符在参数中无法识别

c++ - 默认参数有什么问题?

c++ - 迭代不断变化的容器

c++ - 通过合并排序计算数组中的反转

java - 多线程ArrayList迭代

c++ - 为 std::vector<std::vector<TYPE>> 中的内部 vector 保留内存

c++ - 汇编代码中的静态值