10

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

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

这是与我的实际程序具有相同结构的简化代码。在异步运行时调用Start()andKill()会导致崩溃,因为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;
    }
};

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

4

1 回答 1

10

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

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

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

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

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

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

于 2013-01-13T17:13:26.217 回答