将std :: future类成员声明为可变的线程安全吗?

时间:2019-09-23 21:52:44

标签: c++ thread-safety mutable std-future

std::future声明为mutable是否安全(线程安全),因为其get()函数会更改其状态。我假设它像std::mutex一样可以安全地制成mutable

template <typename T>
struct S {
    void query() {
        m_fut = doAsyncQuery();
    }

    template <typename L>
    void get(L lambda) const {
        lambda(m_f.get());
    }

    mutable std::future<T> m_f;
};

1 个答案:

答案 0 :(得分:2)

它是线程安全的吗?

不,但这没关系。

std::future仅用于单线程,并且在设计上也不是线程安全的。在多个线程之间共享它是没有意义的。您应该只打一次get(),然后扔掉它。

(运行附加操作并设置get()返回的值的线程在这里不相关。该实现为您管理和隐藏了必要的同步。)

(当然,您可以将std :: future的所有权从一个线程转移到另一个线程。但是在任何给定时间,只有一个线程应该持有并使用std :: future。)

可变吗?

是的。实际上,std::future不能为const,因为在附加操作完成时和调用get()时,其状态会根据定义更改。

但是mutable不应是此处要查找的关键字。当然,您可以使用std::future关键字将class包裹在structmutable中,然后创建该类的const实例,但是您隐藏了删除了一条重要的信息(即包装器根本不是const)。 (在更复杂的类中可能有意义,但我认为具有std :: future成员的复杂类是不良设计的标志。)

相反,您也应该使此类包装器类或struct non-const:

template <typename T>
struct S {
    void query() {
        m_fut = doAsyncQuery();
    }

    template <typename L>
    void get(L lambda) {    // remove const here
        lambda(m_f.get());
    }

    std::future<T> m_f;     // remove mutable here
};

只要您知道S的实例不能为const,就只能调用get一次,并且您不应该在线程之间共享S,你应该很安全。