是Clojure"发送"异步?

时间:2011-04-14 20:11:34

标签: clojure

我正在使用Java new I/O package为Clojure编写一个简单的网络框架。它管理一个“选择器代理”池,每个选择器代理都包含Selector

我为选择器代理定义了dispatch操作。此操作会阻止对selector.select()的调用。当返回时,选择器代理迭代所选键并执行I / O.完成I / O后,选择器代理会使用send-off自行发送dispatch操作,有效地循环调用selector.select()

当我想添加新频道或更改频道的interest ops时,我会向选择器代理发送相应的操作,然后取消阻止选择器(它在select()上被阻止,请记住吗?)。这可确保选择器代理中的(send-off selector-agent dispatch)(send selector-agent add-channel channel)后执行


我认为这是防弹的,因为在选择器唤醒之前执行对send-off的调用,因此,在选择器代理向自己发送dispatch动作之前。但是,这会产生不一致的行为。有时,dispatch操作首先发生,有时则不发生。

我的理解是,无法保证代理按照它们来自多个线程时发送的确切顺序执行操作(即sendsend-off在排队操作方面不同步)。

这是对的吗?

3 个答案:

答案 0 :(得分:6)

sendsend-off保证在单个线程内按照发送顺序将操作放在代理的队列中。更新代理的队列同步发生。

我希望你有一个简单的竞争条件,虽然我无法从描述中识别它。

答案 1 :(得分:1)

你是对的。来自同一线程的操作将按照提交的顺序执行。但是你不能对来自不同线程的动作的执行顺序做出任何假设。

答案 2 :(得分:1)

发送和发送是为异步状态更改而构建的。 如果你需要同步更新,那么原子可能是你最好的工具。

因为您需要保留请求的顺序,您可能必须使用并发对象(atom)中的另一个数据结构才能同步更新。将持久化队列置于一个原子中并使所有线程同步性添加到该队列,同时消费者同步从中拉出条目。

这是超级简短的决策图:

  • 多个并且同步:使用ref
  • 异步:使用代理
  • 异步多个:dosync中的代理
  • 同步且只有一个:使用代理。