我正在使用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
操作首先发生,有时则不发生。
我的理解是,无法保证代理按照它们来自多个线程时发送的确切顺序执行操作(即send
和send-off
在排队操作方面不同步)。
这是对的吗?
答案 0 :(得分:6)
send
和send-off
保证在单个线程内按照发送顺序将操作放在代理的队列中。更新代理的队列同步发生。
我希望你有一个简单的竞争条件,虽然我无法从描述中识别它。
答案 1 :(得分:1)
你是对的。来自同一线程的操作将按照提交的顺序执行。但是你不能对来自不同线程的动作的执行顺序做出任何假设。
答案 2 :(得分:1)
发送和发送是为异步状态更改而构建的。 如果你需要同步更新,那么原子可能是你最好的工具。
因为您需要保留请求的顺序,您可能必须使用并发对象(atom)中的另一个数据结构才能同步更新。将持久化队列置于一个原子中并使所有线程同步性添加到该队列,同时消费者同步从中拉出条目。
这是超级简短的决策图: