我正在写一些设置类,可以在我的多线程应用程序中随处访问。我会经常阅读这些设置(所以阅读访问应该很快),但是它们不会经常被写入。线程安全设置
因为看起来boost::atomic
基本数据类型提供了我需要什么,所以我想出了这样的事情:
class UInt16Setting
{
private:
boost::atomic<uint16_t> _Value;
public:
uint16_t getValue() const { return _Value.load(boost::memory_order_relaxed); }
void setValue(uint16_t value) { _Value.store(value, boost::memory_order_relaxed); }
};
问题1:林不知道有关内存排序。我认为在我的应用程序中,我并不真正关心内存排序(是吗?)。我只是想确保getValue()
始终返回一个未损坏的值(旧的或新的)。那么我的记忆顺序设置是否正确?
问题2:这种方法使用boost::atomic
推荐用于这种同步吗?还是有其他构造可以提供更好的阅读效果?
我的应用程序中还需要一些更复杂的设置类型,如std::string
或例如boost::asio::ip::tcp::endpoint
s的列表。我认为所有这些设置值都是不变的。因此,一旦我使用setValue()
设置了该值,则该值本身(std::string
或端点本身列表)不再更改。所以我只是想确保我得到旧值或新值,但不是一些损坏的状态。
问题3:这种方法是否适用于boost::atomic<std::string>
?如果不是,有什么替代方案?
问题4:更复杂的设置类型如端点列表如何?你会推荐类似于boost::atomic<boost::shared_ptr<std::vector<boost::asio::ip::tcp::endpoint>>>
吗?如果不是,那会更好吗?
重新检查允许多个线程在需要时读取和写入这些设置的要求。一个线程调用getBlahSetting()并获得一个结果是否有意义,并且在同一个函数中,稍后再调用它并得到一个_different result_?我建议你在硬同步点设计。 – David
设置只能代表用户更改,用户很少能同时执行多个操作。就目前而言,不应该有一个以上的作家。因此,我会访问(=读取)配置,而没有任何同步(因为它经常发生)。在配置发生改变的罕见情况下,从修改线程进行深层复制(再次,这不需要同步)。然后对指向每个人都使用的配置对象的指针执行一个'seq_cst'存储(这很昂贵,但是您可以承担,因为它很少发生),并且完成。它可能需要... – Damon
...在其他线程接受更改之前的一段时间,但这通常不是问题。他们最终会。如果这是一个问题*,你别无选择,只能使用锁(可能是读写器锁),然后性能会很差。或者,线程可以保留配置状态的本地副本(或共享一个ref-counting副本),并在明确的时间通知_explicitly_通过任务队列更新配置。这消除了可能的比赛。 – Damon