2011-10-04 31 views
0

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

回答

1

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

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

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

+0

+1我的印象是,这是语言不可知的,但谢谢你的澄清。我修改了我的标签,以表明我正在使用的是什么。 – Legend

1

没有,即使代理代码是高度怀疑和看起来很危险,我没有看到,在这种情况下它产生的竞争条件:msgsRcvd应始终以正确的总告终。即使调度程序在增量之前中断agent1,在我看来,控制总是会回来让增量完成。如果控制器获得控制权,那么它可能会报告MsgsRcvd的不准确内容,但那又如何? MsgsRcvd快速恢复阶段。

虽然它确实是一段令人恐怖的代码。当我在查看这种代码时,我总是希望将MsgsRcvd的增量向上移动到控制器中,从而暴露出将执行增量的功能。但是这只会让我在这种情况下感觉更好。它不会改变逻辑,它不会解决MsgsRcvd暂时不准确的“问题”(如果它是一个)。

+0

+1为移动增量的建议。是。我正要在'Controller'类中实现'setter/getter',但我注意到它不会改变逻辑。无论如何,我会继续前进并进行更改,因为它只是使代码看起来更清晰。 – Legend

+0

好主意。然后我会感觉*多*更好:-) –

1

最初是要提到的是,没有语言/平台不可知的方式来回答这个问题,但埃里克J.已涵盖。

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

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

+0

+1谢谢你的时间。我将不得不深入仿真引擎ns-3来确定如何完成。也许我会在他们的留言板上发布一个问题。 – Legend

+0

@Chuu:如果有多个线程接收事件,这是一个很好的观察。包括Java和C#在内的许多语言也是如此,原因在于增量操作符实际上代表三个离散操作(将值加载到寄存器,递增该寄存器并将该值存回内存)。 –