1

问题很简单,但我相信解决方案(如果存在的话)相当复杂。无论如何,我目前正在开发一个分布式应用程序,它应该通过使用线程并行实现简单的事务处理(PRINT、ADD、SLEEP、ASSIGN 等)(我正在使用 Pthreads 进行此分配)。正如预期的那样,我在尝试同时处理多个冲突事务(可能高达 20 个)时出现死锁问题。

现在,我决定为每个线程的事务处理实现多次重试,这些线程基本上是随机生成的,srand(time(NULL))rand()以该顺序精确调用。问题是,当处理多个事务(最多 5 个不同的服务器)时,数字匹配,因为它们基本上是在同一时间生成的。

所以,我的问题是,有没有一种方法可以完全随机生成整数而不使用该time()函数,而是使用其他方法?

提前感谢您的任何帮助,并对(太)长的描述感到抱歉。

4

3 回答 3

1

要在不同线程之间拥有独立的伪随机生成器 PRG,您必须更加小心。基本上,您必须将生成器的状态保存在每个线程的单独变量中,并使用每个线程不同的东西初始化每个状态一次。例如,使用时间和线程 ID 进行初始化。

由于您在 POSIX 系统上,您可以jrand48作为生成器函数,但是任何允许您将状态作为参数传递的随机生成器都应该没问题。

于 2013-06-13T22:00:33.283 回答
0

您不应该srand()在每次调用rand(). 这就是你的问题的根本原因。相反,您应该srand()只在程序启动时调用一次,然后再创建线程。

此外,rand()在 POSIX 上不需要是线程安全的,因此您应该使用互斥锁来序列化从不同线程对其的访问。

于 2013-06-14T05:03:51.743 回答
0

正如您所观察到的,当多个 PRNG 使用相同的值播种时,使用 PRNG 计算退避和重试时间不起作用。如果冲突具有破坏性,则两个会话将使用相同的重试时间并无限期地继续相互取消。

如果这只是在单台计算机上运行的一个任务多线程应用程序,那么您可以尝试使用线程 ID 作为 PRNG 种子。

如果分布可以比单个任务更广泛,那么您最终会遇到将所有唯一标识符组合成一个适合种子值大小的唯一标识符的问题。虽然独立线程的数量可能足够少,但可预测的唯一转换可能很困难。

也许作为每个线程启动的一部分,您应该连接到竞争资源并获取唯一的会话 ID。如果您可以错开不同线程的启动,那么您就不必处理争用(只需在第一个线程确认它得到它的 ID 之前拒绝启动另一个线程)。如果这是不可能的(例如,在广泛分布的情况下),您将不得不从其他一些随机源计算重试时间,例如/dev/urandom.

但是,如果可以只为n同时请求之一提供服务,则此问题可以自行解决。

n同时请求中,一个客户端得到响应并继续,同时n-1必须重试。不成功的客户端将推进他们的 PRNG 状态,而其他的则不会。如果他们都具有相同的 PRNG 状态,那么他们都会再次竞争,但一个会通过,其他人会再试一次。最终,所有人都将通过冲突(一个接一个)并拥有独特的 PRNG 状态。

于 2013-06-17T11:04:43.627 回答