请考虑服务器上的以下定义:
f:{show "Received ",string x; neg[.z.w] (`mycallback; x+1)}
在客户端:
q)mycallback:{show "Returned ",string x;}
q)neg[h] (`f; 42)
q)"Returned 43"
在q for motrtals
中,提示说:
执行异步消息传递时,请始终使用neg [.z.w]来确保 所有消息都是异步的。否则你会陷入僵局 因为每个进程都在等待对方。
因此,我将服务器上的定义更改为:
f:{show "Received ",string x; .z.w (`mycallback; x+1)}
一切都很好,而且我还没有看到任何僵局。
谁能给我一个例子来说明为什么我应该始终使用neg[.z.w]
?
答案 0 :(得分:7)
如果我理解您的问题是对的,我认为您是在询问同步和异步消息的工作方式。您提供的示例的问题在于x + 1是一个非常简单的查询,几乎可以立即对其进行评估。对于一个更具说明性的示例,请考虑将其更改为睡眠(或更费劲的计算,例如大型数据库查询)。
在服务器端定义:
f:{show "Received ",string x;system "sleep 10"; neg[.z.w] (`mycallback; x+1)}
然后,您可以在客户端发送同步查询:
h(`f; 42)
多次。这样做,您将看到客户端不再有q提示,因为它必须等待响应。这些请求可以排队,从而在相当长的时间内阻塞了客户端和服务器。
或者,如果您要致电:
(neg h)(`f; 42)
在客户端。您将看到q提示符仍然存在,因为客户端不等待响应。这是一个异步调用。
现在,在服务器端功能中,您正在使用.z.w或neg .z.w。从服务器角度来看,这遵循完全相同的原理。如果对查询的响应足够大,则消息传递可能会花费大量时间。因此,通过使用neg,该响应可以异步发送,因此在此过程中不会阻止服务器。
注意:如果您在Windows计算机上工作,则需要按照睡眠方式换掉超时,或者如果遵循我的示例,则可能需要进行while循环。
更新:我想导致这种死锁的一种方法是拥有两个从属进程,试图彼此同步调用。例如:
q)\p 10002
q)h:hopen 10003
q)g:{h (`f1;`)}
q)h (`f;`)'
一侧和
q)\p 10003
q)h:hopen 10002
q)f:{h (`g;`)}
q)f1:{show "test"}
另一方面。这将导致两个进程都卡住,从而导致永远无法显示测试。
答案 1 :(得分:0)
Joe的答案涵盖了几乎所有内容,但是对于您的特定示例,如果客户致电
,则会发生死锁h (`f; 42)
在处理下一个请求之前,客户端正在等待服务器的响应,但是在完成客户端的请求之前,服务器也在等待客户端的响应。