c++ std::shared_ptr自定义删除线程安全



[用更具体的例子编辑]

假设我有一个线程安全的对象(所有公共成员都使用互斥对象)和一个带自定义删除器的shared_ptr,如下所示:

class A {
public:
void update(int x);
void print_sum();
...
}
class AContainer {
private SomeConcurrentMap<string, shared_ptr<A>> aMap;
void newA(string name) {
aMap.emplace(name, shared_ptr<A>(new A, [](A *p){p->print_sum(); delete p;}));
}
void finalizeA(string name) {
aMap.erase(name);
}
shared_ptr<A> getA(string name) const {
// fixme handle case of not found...
return aMap.find(name).second;
}
};
void someFunctionInSomeThread(const AContainer &cont, string name, int c) {
// fixme handle case of not found...
cont.getA(name)->update(c);
}

让我们假设所有A操作都由互斥锁保护,并且SomeConcurrentMap是线程安全的。使用场景为:

  1. 从任意线程调用AContainer::newA()
  2. 通过多个线程多次调用someFunctionInSomeThread()
  3. 从任何线程调用AContainer::finalizeA()-可能与步骤2并行

以及A::print_sum()在步骤3完成和所有运行的A::update()操作完成后被调用的想法

是否可以假设在调用p->print_sum()时,对象上的所有A::update()操作都已调用?

是否可以假设在调用p->print_sum()时,对象上的所有A::update()操作都已调用?

是的,可以安全地假设。只有一个线程会调用析构函数,并且没有线程会在调用A的其他成员函数之前调用析构函数(这样的线程即使没有其他线程存在也会调用UB,例如,在销毁共享指针后保留一个原始指针,然后通过原始指针访问对象)。