我有一个建筑师类似下面的代码.
struct Object {
Object(int& n) : value{n} {}
int& value;
}
struct Accessor {
Accessor(const int& o) : o_(o) {}
const int& getValue() {
return o_;
}
private:
const int& o_;
}
struct Mutator {
Mutator(int& o) : o_(o) {}
int& getValue() {
return o_;
}
private:
int& o_;
}
struct ObjectA : Object {
shared_ptr<const Accessor> getAcc() {
return make_shared<Accessor>(Accessor{value});
shared_ptr<Mutator> getMut() {
return make_shared<Mutator>(Mutator{value});
}
目标是使用mutator写入对象值,使用accessor读取对象值。
我已经编写了单元测试,所有测试都运行良好。
我觉得它在多线程下运行时可能会有问题。我想知道mutator和accessor是否是线程安全的?如果不是,我如何改进它们使之成为线程安全的?
1条答案
按热度按时间mf98qq941#
不,您所显示的代码不是线程安全的。
按照您编写代码的方式,* 任何 * 线程都可以在 * 任何 * 时间读/写引用的
int
变量,而无需 * 任何 * 线程之间的同步。如果您允许一个线程在其他线程从int
阅读的同时向int
进行 * 写入 *,则可能发生不好的事情,因此,您必须 serialize 访问,以便写入线程获得对int
的独占访问。请查看使用std::mutex
、std::atomic
或等效方法进行同步。另外,
Object
中的int&
引用是公共可访问的,而ObjectA
是从Object
公共继承的,所以引用的int
对所有外部代码都是公共可访问的,因此 * 任何 * 线程都可以完全绕过访问器/赋值器。使得X1 M13 N1 X是私有的而不是公共的,并且 * 不 * 让accessor/mutator返回对int
的引用。这只允许调用方获取引用,然后在需要时直接访问int
。在accessor/mutator类来强制对int
的所有访问都只通过它们。试试这样的方法:
话虽如此,你为什么要使用
std::shared_ptr
呢?在这类代码中没有必要使用std::shared_ptr
。你的getter/mutator可以直接通过值而不是动态指针返回类对象,例如:尽管如此,在这种情况下,我并不建议使用单独的access/mutator类,因为它们有点多余,例如:
或者: