如何取消std :: async函数?

dan*_*jar 7 c++ crash multithreading c++11 stdasync

可能重复:
有没有办法在C++ 11中取消/分离未来?

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

这是简化的代码,其结构与我的实际程序相同.在异步运行时调用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;
    }
};
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*ely 9

既然没有人真正回答了这个问题,我会这样做.

running变量的写入和读取不是原子操作,因此代码中没有任何内容导致两个线程之间的任何同步,因此没有任何东西可以确保异步线程看到变量已更改.

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

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

显然,在此代码中,如果running函数启动后发生更改,则不会导致循环停止.

C++标准允许您同步两个线程有​​两种方法,即使用互斥锁并仅running在互斥锁被锁定时读取或写入变量,或者使变量成为原子变量.在您的情况下,running从更改boolatomic<bool>将确保对变量的写入与其读取同步,并且异步线程将终止.