我有以下代码片段应该模拟挖掘比特币,但我在它自己的线程上运行每个“节点”。我想要做的是让所有节点同时开始挖掘,但是当其中一个节点完成时,其他节点应该停止。由于某种原因,这是行不通的。目前正在发生的事情显然只允许第一个节点开采而其他节点什么都不做。
chosen = self.nodes
q = Queue()
# to simulate concurrent mining, each client will get their own thread
# and when one of them finds a correct nonce, the others will stop
for node in chosen:
Thread(target=node.mine, args=(txdata, lastblock, q)).start()
return q.get()
node.mine()
只是尝试找到以5个零开头的块和一个随机数(总是从0开始的所有节点)。我使某些节点比其他节点更快地开采的方式是它们每个都有一个代表其功率的随机数,并且在node.mine()
中,每个节点在执行任何操作之前都会休眠1/power
秒。
答案 0 :(得分:1)
正如评论中指出的那样,一次只运行一个线程的事实是因为q.get()
调用在循环内部。这将阻塞,直到结果准备就绪,这有效地序列化了线程。在循环之外移动将在检查队列之前启动所有线程。
但是,这并不能解决您在完成后退出其他线程的问题。最好的"这样做的方式实际上取决于node.mine()
方法的结构。
例如,如果它是某种循环,通常如下:
while True:
relatively_fast_computation()
然后你可以添加threading.Event()
或类似的混合,并让每个线程检查是否设置了事件而不是无限循环。
while not event.is_set():
relatively_fast_computation()
主线程等待队列上的结果,当收到一个结果时,设置事件。工作线程然后注意到下一次通过while循环并退出。这可能是首选方法,因为它允许工作线程正确退出,清理,关闭文件等。
这里的问题是,如果每次遍历while循环都非常慢,这将无法正常工作,如果其中的函数真正阻塞,它将无法正常工作,就像在网络I / O中一样。在这种情况下,有一些解决方法,但没有一个听起来很棒或特别适用于您的情况。
编辑:
正如评论中也指出的那样,如果node.mine()
方法是一个纯粹的CPython函数,那么这里的线程可能是无用的。 GIL将阻止像哈希这样的CPU绑定代码无论如何都要运行多个线程。使用multiprocessing
。