我正试图想出一种方法,让线程在同一个目标上工作而不受干扰。在本例中,我使用4个线程将0和90000之间的每个数字相加。此代码运行时几乎立即结束(运行时:0.00399994850159秒),只输出0。最初我想用一个全局变量来实现,但我担心线程之间会相互干扰(即,由于奇怪的读/写时间,两个线程重复计数或跳过一个数字的可能性很小)。所以我提前分配了工作量。如果有更好的方法,请分享。这是我尝试获得多线程经验的简单方法。谢谢
import threading
import time
start_time = time.time()
tot1 = 0
tot2 = 0
tot3 = 0
tot4 = 0
def Func(x,y,tot):
tot = 0
i = y-x
while z in range(0,i):
tot = tot + i + z
# class Tester(threading.Thread):
# def run(self):
# print(n)
w = threading.Thread(target=Func, args=(0,22499,tot1))
x = threading.Thread(target=Func, args=(22500,44999,tot2))
y = threading.Thread(target=Func, args=(45000,67499,tot3))
z = threading.Thread(target=Func, args=(67500,89999,tot4))
w.start()
x.start()
y.start()
z.start()
w.join()
x.join()
y.join()
z.join()
# while (w.isAlive() == False | x.isAlive() == False | y.isAlive() == False | z.isAlive() == False): {}
total = tot1 + tot2 + tot3 + tot4
print total
print("--- %s seconds ---" % (time.time() - start_time))
你有一个错误,使这个程序几乎立即结束。看看
while z in range(0,i):
中的Func
。z
不是在函数中定义的,只有运气好(真的是运气不好),您碰巧有一个全局变量z = threading.Thread(target=Func, args=(67500,89999,tot4))
掩盖了问题。您正在测试线程对象是否在整数列表中。。。不是这样的!你知道吗下一个问题是全局变量。首先,使用一个全局变量不是线程安全的,这是绝对正确的。这些线程会互相干扰。但你误解了全局的工作原理。执行
threading.Thread(target=Func, args=(67500,89999,tot4))
时,python将当前由tot4
引用的对象传递给函数,但函数不知道它来自哪个全局。只更新局部变量tot
,并在函数完成时丢弃它。你知道吗一个解决方案是使用一个全局容器来保存计算,如下面的示例所示。不幸的是,这实际上比仅仅在一个线程中完成所有工作要慢。python全局解释器锁(GIL)一次只允许运行一个线程,并且只会降低纯python实现的CPU密集型任务的速度。你知道吗
您可以查看
multiprocessing
模块,将其拆分为多个进程。如果运行计算的成本与启动进程并向其传递数据的成本相比是很大的,那么这种方法很有效。你知道吗以下是您的示例的工作副本:
正如其他人所指出的,您可以查看
multiprocessing
,以便将工作拆分为多个可以并行运行的不同进程。在CPU密集型任务中,如果进程之间没有大量的数据可供传递,这将特别有益。你知道吗下面是使用^{} 对相同功能的简单实现:
在上面的} ,其工作原理与标准
chunks
是一个生成器,它生成与原始版本中硬编码的范围相同的范围。它被赋予了^{map
相同,只是它在池中的进程中执行函数。你知道吗关于
multiprocessing
鲜为人知的事实是,通过使用未记录的multiprocessing.pool.ThreadPool
,您可以轻松地将代码转换为使用线程而不是进程。为了将上述示例转换为使用线程,只需将import
更改为:您可以传入一个可变对象,该对象可以使用标识符添加结果,例如
dict
或仅使用list
和append()
添加结果,例如:相关问题 更多 >
编程相关推荐