【发布时间】:2014-02-13 22:02:35
【问题描述】:
C++ 标准库对其类型提供以下保证,除非另有说明:
(1) 读取操作(即处理const 对象)是线程安全的。这意味着只要没有线程同时向对象写入(应用非const 操作),多个线程就可以同时从一个对象读取而没有竞争条件。
(2) 多个线程可以同时读取和写入任意对象,只要每个对象一次最多只能被一个线程访问。
标准库需要用户类型的相同保证。 (您可以在GotW #95 中阅读有关这些内容的信息,或观看Herb at C++ and Beyond 2012 对此的解释。)
现在我的问题是,如果下面的结论是正确的:由于std::function 的operator() 是const 成员函数,所以它必须是线程安全的。如果在构造时传入的仿函数有一个 const operator() 成员函数,那么 std::function 对象可以假定它是线程安全的并且只是转发调用。但是,如果在构造时传递给它的函子有一个可变的operator(),那么这个操作不需要是线程安全的,但std::function 仍然需要,因为调用运算符仍然是 const。因此std::function 必须在外部同步对存储的可变函子的调用,因此使用互斥锁。这意味着在将可变 lambda 传递给 std::function 的构造函数时会产生性能开销。
这个推理正确吗?如果是这样,当前的实现是否兼容?
【问题讨论】:
-
我不知道 std::function 是否真的获得了一个互斥体,但如果确实获得了,它也不会有太大帮助,因为它无法控制它没有进行的调用。因此,如果它这样做,我会感到惊讶。一般来说,没有办法自动使线程不安全的代码成为线程安全的。如果你希望你的代码是线程安全的,你需要自己处理同步。
标签: c++ c++11 locking mutex functor