C中链表的并发修改

Concurrent modification of linked list in C

我编写了一个 C 应用程序来对 DNS 服务器进行压力测试(运行 在 VM 上),我正在尝试获得最大 DNS 请求率(吞吐量)以查看其行为方式。
我的应用程序运行两个线程,发送线程生成 DNS 请求(具有不同的查询名称)并在套接字上将它们发送到服务器,接收线程在同一套接字上接收 DNS 响应并计算响应时间。

现在使用并发链表(我已经实现),发送线程为每个发送的请求附加查询名称和发送时间(到列表的末尾)。接收线程每次从头开始运行,查找具有相关发送时间的查询名称,计算响应时间并从列表中删除对象,它遍历的每个对象都会检查发送时间是否在 DNS 超时范围内 window 我已设置,如果未设置,我会将此请求视为未答复并将其从列表中删除。

现在的问题是,每次在接收线程中遍历整个列表时我都必须锁定,其中也包含节点删除,它严重影响停止发送的发送线程,在锁上等待很多时间追加。

在我的案例中,您是否建议采用不同的方式来实施锁定?或者我可以改变更重要的事情吗?

PS: 我尝试在脚本中使用 unix dig 并在 python scapy 中实现相同但无法达到速率我正在使用 C 应用程序(无锁定发送高达 10 Mbit),这就是我选择在 C 中实现它的原因。

谢谢!

您可能不需要在接收线程扫描它时锁定整个列表。发送线程只会修改当前的最后一个节点(以附加一个新节点),并且它不需要检查任何其他节点,只要它维护指向当前尾部的指针即可。就其本身而言,接收线程然后可以删除当前尾部以外的任何节点,而不会对发送线程产生任何影响。因此只需要锁定尾节点。

在当前尾部保持移动锁可能有点棘手,因为你需要知道哪个节点,但我认为不会太难。例如,您可以提供指向尾部的共享原子指针,发送方在发送每个请求之前更新它,接收方在收到响应时读取它。接收方不需要考虑任何后续请求(因为在收到当前响应时它们尚未发送)。

接收方有时可能需要等待发送方附加至少一个请求,以便可以删除以前的尾巴,但我希望这种情况很少见。否则,我不明白你的列表现在怎么会变得如此之长,以至于在扫描它的时候把整个东西都锁定了time-consuming。