这会导致事件驱动编程中的竞争条件吗?

时间:2011-10-04 22:29:31

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

我正在离散模拟器中编写一个基于代理的小型交互模拟,并开始编写一些如下所示的代码。我以前没有一些事件驱动的编程,但没有真正观察到这种情况。我想知道在更新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)?有什么建议吗?

3 个答案:

答案 0 :(得分:1)

答案取决于您的事件传输的实现,并且在这个意义上不是语言不可知的。

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

如果您的事件队列具有某些尝试根据时间戳合并事件的智能,则您只能在接收代理中看到一个事件。我不知道有一个共同的系统可以做到这一点(虽然一些UI系统可能例如将两次快速鼠标点击合并为双击......但这是特定事件系统的特定行为,而不是语言/平台不可知)。 / p>

答案 1 :(得分:1)

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

但是,这确实是一段可怕的代码。当我看到这种代码时,我总是希望将MsgsRcvd的增量移动到控制器中,在那里公开一个将执行增量的函数。但这只会让我在这种情况下感觉更好;它不会改变逻辑,也不会解决MsgsRcvd暂时不准确的“问题”(如果是一个)。

答案 2 :(得分:1)

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

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

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