3

http://www.zeromq.org/blog:multithreading-magic

基于消息的 ZeroMQ 框架在不使用锁的情况下实现并发/多线程应用程序。

问题> 对于以下示例,它实际上是如何工作的?

例如:

我们有两个客户端,每个客户端都从同一个数据库中读取数据,然后放回修改后的结果。

ClientA: Read data A, modified A.value = A.value + 1 then write data A back to database
ClientB: Read data A, modified A.value = A.value + 2 then write data A back to database

问题> 我不知道如何用 ZeroMQ 实现这样的系统,这样我就不需要锁来控制 ClientA 和 ClientB 的行为。如何防止以下情况的发生。

ClientA read data A first
ClientB read data A second
ClientB write data A back // now data.value has been increased by two
ClientA write data A back // now the conflict! because the original value of A has been 
                          // modified by ClientB and ClientA has no information about it.
                          // If ClientA writes the A back without knowing the update A
                          // then the changes made by ClientB will be voided.

ZeroMq 如何在不使用锁的情况下通过使用它的消息来解决这样的问题?

谢谢

4

2 回答 2

1

ZeroMQ 为您提供了一个工具箱,可以让您解决这个问题,但最好的解决方案很大程度上取决于细节。

例如,如果客户端用更新来敲击服务器,但客户端的唯一意图是增加 A,它可以简单地向服务器发送一条包含要增加的值的消息,而不知道 A 的确切值。

更一般地说,服务器可以向客户端发布更新,客户端可以请求服务器更新 A 的值,就像在集群哈希映射协议中一样。然而,据我所知,该协议不会检测到对同一密钥的并发更新。您可以修改它以添加乐观锁定或尝试在协议之上构建一些东西。示例实现让服务器在单个线程中执行更新并对更新进行编号,因此您可以使用该序列号。但这仍然需要一些努力。

有关该协议的更多详细信息,请参阅ZeroMQ 指南

于 2013-05-04T16:20:05.803 回答
1

一个简单的答案是您可以使用并发队列模拟锁。

假设您有一个大小为 1 的队列已满。客户端将尝试从队列中获取一个值。成功的将执行操作并将值放回队列中。失败的将进入睡眠状态,并在成功的客户端完成后继续。

这可以说是一个学术例子。实际上,您可能会在数据库系统中使用事务,而不是在客户端之间使用锁。

于 2013-05-02T23:14:29.087 回答