首页 > 解决方案 > 如何使用线程添加n个自然数

问题描述

我想添加 n 个自然数,但将其分成不同的线程。我已经实施了。但是,我最终无法获得总和。请帮助使用同步,使用全局变量和锁定机制。

我用过线程。假设我要加 30 个自然数,分成三个线程,每个线程求和 10 个自然数,我得到的答案是每个线程的总和,我想得到 30 的总和。

我正在使用 Python 2.7

我的代码:

import threading


a=input("Enter first number")
b=input("Enter second number")

sum=0

def add_func(a,b):
    result=0
    for i in range(a, b+1):
        result =result + i
    print result

if __name__ == "__main__":
    t1 = threading.Thread(target=add_func(1, 10))
    t2 = threading.Thread(target=add_func(11, 20))
    t3 = threading.Thread(target=add_func(21, 30))


    t1.start()
    t2.start()
    t3.start()

输出 :

Enter first number1
Enter second number30
55
155
255

标签: pythonmultithreading

解决方案


即使没有GIL(如果你在 CPython 中),这个问题的线程版本也会比math慢,所以我假设这纯粹是出于教学目的。

Python 中的线程主要用于 IO 密集型工作,而不是 CPU 密集型工作(但请查看多处理模块以了解 CPU 密集型工作)。

您可以通过多种方式从线程返回结果。一种方法是传入一个结果列表并为每个线程提供一个唯一的 ID 号,该 ID 号可用于索引到列表中。当一个线程完成它的任务时,它会在结果列表中填充它的桶,在线程全部重新加入后,它在调用代码中可用。

另一种方法可能是使用共享变量或来强制对共享数据进行互斥(如果 GIL 还没有这样做……),但这对于这种情况来说感觉有点过分了。

这是代码:

from threading import Thread
from math import ceil

def add_func(i, res, start, end):
    total = 0

    for n in range(start, end):
        total += n

    res[i] = total

if __name__ == "__main__":
    a = 67
    b = 131
    num_threads = 4
    threads = []
    res = [None] * num_threads
    step = ceil((b - a) / num_threads)

    for i in range(num_threads):
        t = Thread(
            target=add_func, 
            args=(i, res, a, min(b, a + step) + 1)
        )
        threads.append(t)
        t.start()
        a += step + 1

    for thread in threads:
        thread.join()

    print(sum(res))

或者这是解决这个特定问题的快速方法:

a = 67
b = 130
print((abs(a - b) + 1) * (a + b) / 2)

推荐阅读