2

当一个线程已经在超时处理程序中时,在上下文切换期间销毁截止时间计时器会发生什么?

例如,如果在 TimerCallback 执行期间,上下文切换到另一个线程删除了 ScheduledCommand?

ScheduledCommand::ScheduledCommand(
        const boost::shared_ptr<CommandInterface> command,
        const boost::posix_time::time_duration timeTillExecution):
    mTimer(TheCommandTimerThread::instance()->IoService(), timeTillExecution),
    mCommand(command)
{
    mTimer.async_wait(boost::bind(&ScheduledCommand::TimerCallback,
                                  this,
                                  boost::asio::placeholders::error));
}

ScheduledCommand::~ScheduledCommand()
{
    Cancel();
}

void ScheduledCommand::TimerCallback(const boost::system::error_code& error)
{
    if (!error)
    {
        assert(mCommand);
        mCommand->Execute();
    }
}

上述代码在 mCommand->Execute() 处存在分段错误。GDB 分析显示 mCommand 无效。可能从另一个线程中删除。谢谢。

编辑:

为什么以下更改不能解决此问题?

ScheduledCommand::Cancel()
{
    if (mTimer.cancel() == 0) 
    { 
        mTimer.wait() 
    } 
}
4

1 回答 1

1

如果在多线程环境中,您在一个线程中删除了一个对象,而在另一个线程中使用它,您可能会发生崩溃,正如您所看到的那样。

当使用 boost::asio 时,如果你取消了定时器,你仍然必须让它执行处理程序(这将得到一个操作被取消的错误),然后你才能安全地销毁对象。根据您的其余设置,有几种方法。手动使用同步原语,使用boost::asio::strand将某些交互限制在单个线程中,或使用boost::shared_ptr确保关键对象在不再被引用之前保持可用。

没有更多信息,很难告诉您最佳选择。

于 2012-10-24T21:26:17.190 回答