【问题标题】:Will this lead to a race condition in event-driven programming?这会导致事件驱动编程中的竞争条件吗?
【发布时间】:2011-10-04 22:29:30
【问题描述】:

我正在离散模拟器中编写一个基于代理的小型交互模拟,并开始编写一些如下所示的代码。我之前没有一些事件驱动的编程,但并没有真正观察到这种情况。我想知道在更新msgRcvd 的值时,以下代码是否会导致竞争条件。

// Following is the event-loop per-se
Controller {
    if (...) {
       SendMessage(currentTime() + 5, i,j)
       SendMessage(currentTime() + 5, i,k)
    }
    print currentTime(), msgsRcvd
    Schedule(currentTime()+1, Controller)
}

// The following function is called when an 
// agent receives a message
Receive(Agent agent) {
    if (...) {
       msgsRcvd++ // <-- this is a global variable
    }
}

我的理解是,在currentTime() + 5,两个代理都在同时收到消息,因为这两个事件发生在同一个逻辑时间,所以我应该看到消息的数量是 2 ?或者我会看到一些奇怪的竞争条件发生并且值取决于调度程序(即它可能最终打印 1 或 2)?有什么建议吗?

【问题讨论】:

    标签: c++ events simulation event-driven ns-3


    【解决方案1】:

    答案取决于您的事件传输的实现,并且在这个意义上与语言无关。

    在我使用过的所有系统中,每条消息都会单独放入一个事件队列中,接收代理会按顺序从该队列中取出事件。假设您有一个线程生成消息和一个事件将消息从队列中取出,我看不到竞争条件的机会。

    如果您的事件队列具有尝试根据时间戳合并事件的智能,您将只能在接收代理中看到一个事件。我不知道有一个通用系统可以做到这一点(尽管某些 UI 系统可能会将两次快速鼠标单击合并为一次双击……但这是特定事件系统的特定行为,而不是与语言/平台无关)。

    【讨论】:

    • +1 我的印象是这与语言无关,但感谢您的澄清。我修改了我的标签以表明我正在使用什么。
    【解决方案2】:

    不,即使代理代码高度可疑并且看起来很危险,我认为在这种情况下它不会产生竞争条件:msgsRcvd 应该总是结束加上正确的总数。即使调度程序在增量之前中断 agent1,在我看来,控制总是会回来让增量完成。如果控制器获得控制权,那么它可能会报告MsgsRcvd的不准确内容,但那又如何呢? MsgsRcvd 很快就会恢复正常。

    不过,这确实是一段看起来很吓人的代码。当我查看这种代码时,我总是想将 MsgsRcvd 的增量向上移动到控制器中,在那里公开一个将执行增量的函数。但这只会让我在这种情况下感觉更好。它不会改变逻辑,也不会解决 MsgsRcvd 偶尔暂时不准确的“问题”(如果有的话)。

    【讨论】:

    • +1 关于移动增量的建议。是的。我正要在Controller 类中实现setter/getter,但我注意到它不会改变逻辑。无论如何,我将继续进行此更改,因为它只会使代码看起来更干净。
    • 好主意。然后我会感觉好多了 :-)
    【解决方案3】:

    最初是要提到没有与语言/平台无关的方式来回答这个问题,但 Eric J. 已经涵盖了这一点。

    在 C++ 中,除非您的平台保证回调将被序列化,否则编写的代码将不安全。原因是增量运算符不是原子的,如果两个线程同时尝试更新值,根据获取、添加和存储的顺序,可能会发生任何数量的事情。

    如果这个平台的设计真正考虑了并发性,那么应该有一个“互锁/原子”api 来提供您需要的功能。

    【讨论】:

    • +1 感谢您抽出宝贵时间。我将不得不深入研究模拟引擎 ns-3 以确定这是如何完成的。也许我会在他们的留言板上发布一个问题。
    • @Chuu:如果有多个线程接收事件,这是一个很好的观察。对于包括 Java 和 C# 在内的许多语言也是如此,原因是自增运算符实际上表示三个离散操作(将值加载到寄存器,递增该寄存器,将值放回内存)。
    猜你喜欢
    • 2022-09-23
    • 1970-01-01
    • 1970-01-01
    • 2021-09-03
    • 2014-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多