[英]Is there a way to protect a smart pointer from being deallocated on one thread, when work is being done on another thread?
在我们的程序中,我们有一个记录特定事件(字符串)的 class FooLogger
。 我们使用FooLogger
作为unique_ptr
。
我们有两个线程使用这个unique_ptr
实例:
nullptr
nullptr
)时,线程 2 释放FooLogger
unique_ptr
实例但是,由于错误的交错,有可能在记录时, FooLogger
的成员变量被释放,从而导致EXC_BAD_ACCESS
错误。
class FooLogger {
public:
FooLogger() {};
void Log(const std::string& event="") {
const float32_t time_step_s = timer_.Elapsed() - runtime_s_; // Can get EXC_BAD_ACCESS on timer_
runtime_s_ += time_step_s;
std::cout << time_step_s << runtime_s_ << event << std::endl;
}
private:
Timer timer_; // Timer is a custom class
float32_t runtime_s_ = 0.0;
};
int main() {
auto foo_logger = std::make_unique<FooLogger>();
std::thread foo_logger_thread([&] {
while(true) {
if (foo_logger)
foo_logger->Log("some event");
else
break;
}
});
SleepMs(50); // pseudo code
foo_logger = nullptr;
foo_logger_thread.join();
}
是否有可能使用某种线程同步/锁等来确保foo_logger
实例在记录时不会被释放? 如果没有,有什么好的方法可以处理这种情况吗?
std::unique_ptr
的目的是在std::unique_ptr
超出 scope 时释放实例。 在您的情况下,您有多个线程,每个线程都可以访问该元素,并且拥有的线程可能会在其他用户之前被淘汰。
您要么需要确保所有者线程永远不会在用户线程之前被删除,要么将所有权 model 从std::unique_ptr
更改为std::shared_ptr
。 std::shared_ptr
的全部目的是确保 object 只要您使用它就一直存在。
您只需要弄清楚程序需要什么并使用正确的工具来实现它。
使用与 object 消失不同的机制来确定何时停止。
(当你将一个东西用于两个不同的目的时,你经常会遇到麻烦。)
例如,一个原子bool
:
int main() {
FooLogger foo_logger;
std::atomic<bool> keep_going = true;
std::thread foo_logger_thread([&] {
while(keep_going) {
foo_logger.Log("some event");
}
});
SleepMs(50);
keep_going = false;
foo_logger_thread.join();
}
听起来std::weak_ptr
在这种情况下可以提供帮助。
您可以从std::shared_ptr
制作一个并将其传递给记录器线程。
例如:
class FooLogger {
public:
void Log(std::string const& event) {
// log the event ...
}
};
int main() {
auto shared_logger = std::make_shared<FooLogger>();
std::thread foo_logger_thread([w_logger = std::weak_ptr(shared_logger)]{
while (true) {
auto logger = w_logger.lock();
if (logger)
logger->Log("some event");
else
break;
}
});
// some work ...
shared_logger.reset();
foo_logger_thread.join();
}
使用时应使用 make_shared 而不是 make_unique。 并改变:
std::thread foo_logger_thread([&] {
至
std::thread foo_logger_thread([foo_logger] {
它将创建 shared_ptr 的新实例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.