<p>阶乘就是一系列数字的相乘。因为乘法是<a href="https://en.wikipedia.org/wiki/Associative_property" rel="nofollow noreferrer">associative</a>,所以可以按任何顺序乘法。更具体地说,可以将序列分成任意数量的部分,独立地将这些部分相乘,然后组合结果。在</p>
<p>由于CPython的<a href="https://wiki.python.org/moin/GlobalInterpreterLock" rel="nofollow noreferrer">GIL</a>,您可能一次只运行一个线程,但任务的本质可能是简单地练习线程同步。在</p>
<p><a href="https://docs.python.org/3/library/threading.html" rel="nofollow noreferrer">^{<cd1>}</a>和<a href="https://docs.python.org/3/library/queue.html#module-queue" rel="nofollow noreferrer">^{<cd2>}</a>看起来是适合这份工作的工具。我将给出两个可能实现的示例:</p>
<ul>
<li>创建一个<code>Queue</code>和多个<code>Thread</code>对象,每个对象都将
<ul>
<li>乘以预定义的数字范围,然后</li>
<li>将结果放入队列。在</li>
</ul></li>
<li>启动线程并等待它们完成</li>
<li>在主线程中,将队列中的所有数字相乘</li>
</ul>
<p>另一个更有趣的实现是:</p>
<ul>
<li>将所有要相乘的数字压入<code>Queue</code></li>
<li><p>创建多个线程,每个线程将</p>
<ul>
<li>从内部状态1开始</li>
<li>从<code>Queue</code>中取一个数字,如果可以的话(即不阻塞)</li>
<li>把状态乘以它</li>
</ul></li>
<li><p>这里有趣的部分是如何在队列为空后继续操作:</p>
<ul>
<li>线程可以简单地将结果推送到另一个<code>Queue</code>并退出,让主线程在所有线程退出后进行最后的乘法</li>
<li><p>相反,线程可能会将结果推回到队列并退出。但是,您需要以某种方式确保在获得最终结果(并将其推入队列)之前并不是所有线程都退出。在</p>
<ul>
<li><p>一种方法是在联锁计数器中跟踪有多少部分结果被推送到队列中,并防止线程在检测到要处理最后一个结果时退出:</p>
<pre><code>#at initialization
partial_results_lock = threading.Lock()
partial_results_left=<number of threads>
# in the thread, if the queue is empty
with partial_results_lock:
queue.push(state)
state=1
partial_results_left-=1
if partial_result_left!=0: return # after we start over and push
#the final result, the counter will become -1
<start over>
</code></pre></li>
</ul></li>
</ul></li>
</ul>