Kdb 始终使用neg[.z.w]确保所有消息都是异步的?

Kdb 始终使用neg[.z.w]确保所有消息都是异步的?,kdb,Kdb,考虑服务器上的以下定义: 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" 在motrtals的q中,提示说: 执行异步消息传递时,始终使用neg[.z.w]确保 所有消息都是异步的。否则你会陷入僵局 因为每个进程都在等待另一个进程 因此,我将服务器上的定义更改

考虑服务器上的以下定义:

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"
在motrtals的
q中,提示说:

执行异步消息传递时,始终使用neg[.z.w]确保 所有消息都是异步的。否则你会陷入僵局 因为每个进程都在等待另一个进程

因此,我将服务器上的定义更改为:

f:{show "Received ",string x; .z.w (`mycallback; x+1)}
一切都很顺利,我没有看到任何僵局


谁能给我举个例子说明为什么我应该总是使用
neg[.z.w]

如果我理解你的问题是正确的,我想你问的是同步和异步消息是如何工作的。您提供的示例的问题是,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"}

另一方面。这将导致两个进程都被卡住,因此测试永远不会显示。

如果我理解您的问题是正确的,我想您会问同步和异步消息是如何工作的。您提供的示例的问题是,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"}

另一方面。这将导致两个进程都被卡住,因此测试永远不会显示。

Joe的回答涵盖了几乎所有内容,但对于您的特定示例,如果客户端调用

h (`f; 42)

客户机在处理下一个请求之前正在等待服务器的响应,但服务器在完成客户机的请求之前也在等待客户机的响应。

Joe的回答涵盖了几乎所有内容,但是对于您的特定示例,如果客户机调用

h (`f; 42)

在处理下一个请求之前,客户端正在等待服务器的响应,但在完成客户端的请求之前,服务器也在等待客户端的响应。

我不明白你的最后一句话。是的,我在使用windows,我应该使用
\t timeout 10
还是什么?事实上,我在问,如果我不使用
neg.z.w
,为什么会发生死锁,有什么例子吗?@buzhidao首先,对于睡眠替代方案,你可以使用
2_系统[“timeout 3”]
。关于死锁的第二点,我认为这并不意味着字面上的死锁,而是简单地说,例如,由于服务器端运行的进程很长,客户机可能正在等待没有q提示符的响应。这可以在我的示例中看到,同步请求必须等待服务器端的睡眠进行。这可以在我的示例中看到,同步请求必须等待服务器端的睡眠进行。例如,如果存在无限循环,这可能会导致“死锁”。我已在此回复中添加了一个新的更新,因此代码格式正确,我希望这有帮助。我不理解你的最后一句话。是的,我在使用windows,我应该使用
\t timeout 10
还是什么?事实上,我在问,如果我不使用
neg.z.w
,为什么会发生死锁,有什么例子吗?@buzhidao首先,对于睡眠替代方案,你可以使用
2_系统[“timeout 3”]
。关于死锁的第二点,我认为这并不意味着字面上的死锁,而是简单地说,例如,客户机可能正在等待没有q提示符的响应