我目前遇到的问题是必须释放经常被两个不同线程访问的对象(实例)。对我而言,两个线程中的哪一个正在破坏实例并不重要,但我更喜欢那个也创建它的那个,尽管我认为这根本不重要。
因此,在一个应该销毁该对象的线程,检测到它应该被删除,并且在调用析构函数的情况下,另一个线程正在访问该对象的成员(函数),可能是某种运行时会发生错误。
我对这个主题进行了一些研究,但我可以找出人们说:“为什么删除仍然需要存在的对象”。但在我的情况下,在一个线程正在执行的代码决定销毁它之后应该停止需要它。
我希望得到一个答案,比如一本关于这个主题的好书或文章的提示,但随时可以写下如何解决这个问题。
答案 0 :(得分:1)
您需要双重间接,以管理对数据的并发访问:
class Object {
public;
class Data {
int get_value() const;
void set_value(int);
};
class Guard {
public:
Guard(Nutex& mutex, Data* data)
: data(data)
{
if( ! data) throw std::runtime_error("No Data");
mutex.lock();
}
~Guard()
{
mutex.unlock();
}
Data& data() { return *m_data; }
private:
Data* data;
};
class ConstGuard {
public:
ConstGuard(Mutex& mutex, const Data* data)
: data(data)
{
if( ! data) throw std::runtime_error("No Data");
mutex.lock();
}
~ConstGuard()
{
mutex.unlock();
}
const Data& data() const { return *m_data; }
private:
const Data* data;
};
private:
friend std::shared_ptr<Object> make_object(const Data&);
Object(const Data& data)
: data(new Data(data))
{}
public:
~Object()
{
delete data;
}
/// Self destruction.
void dispose() {
Guard guard(get());
delete data;
data = 0;
}
// For multiple operations use a Guard.
Guard get() { return Guard(mutex, data); }
ConstGuard get() const { return ConstGuard(mutex, data); }
// For single operations you may provide convenience functions.
int get_value() const { return ConstGuard(mutex, data).data().get_value(); }
void set_value(int value) { Guard(mutex, data).data().set_value(value); }
private:
mutable Mutex mutex;
data* data;
};
std::shared_ptr<Object> make_object(const Object::Data& data) {
return std::make_shared<Object>(data);
}
(注意:上面的代码只是一个草图,我没有编译它)
这是漫长的故事。简短的是[20.7.2.5] shared_ptr原子访问:
Concurrent access to a shared_ptr object from multiple threads does not
introduce a data race if the access is done exclusively via the functions
in this section and the instance is passed as their first argument.
答案 1 :(得分:0)
应该不销毁对象的线程应该使用std::weak_ptr
来保存它,除非它正在使用它的时间。在这段时间内,weak_ptr
可以升级为std::shared_ptr
。
现在应该销毁它的线程可以在其认为合适的时间内保持其shared_ptr
,然后丢弃shared_ptr
。如果另一个线程只有weak_ptr
(不主动使用它),该对象将消失。如果另一个线程也有一个shared_ptr
,它会保留该对象,直到操作完成。