在GIL存在的情况下,多线程有什么优势?

时间:2019-06-18 13:52:13

标签: python python-3.x multithreading

如果在存在GIL的情况下,在多线程程序中执行的所有子任务是顺序发生的,则它等效于单线程程序。为什么用Python编写多线程程序包(multiprocessing.dummy.Pool,multiprocessing.pool.ThreadPool,并发.futures.ThreadPoolExecutor等)?为什么有人要使用它们? (这与多重处理无关)

2 个答案:

答案 0 :(得分:1)

两件事:

  1. GIL会不时释放。例如,当您尝试执行一些冗长的操作(从文件读取,写入文件,通过网络发送等等)时。这样可以进行一些交错操作-在一个线程中读取,在另一个线程中处理。

  2. 多线程处理不仅具有性能,还具有其他好处-例如易于表达。假设您有两种“并行”运行的算法,它们相互通信并交换数据。您将每种算法放在自己的线程上,进行同步(以确保在可能的时候进行线程切换),然后关闭。如果没有多线程,您将不得不依赖事件编程,这很难且易于扩展。一个很好的例子是各种基于会话的服务器,例如ftp服务器。编写多线程多用户ftp服务器比单线程要容易得多。

通常,是的,如果使用线程执行性能,则python的线程没有意义。但是python不是用来提高性能的,而是用来编写(和修改)代码的简单程度。线程确实对并行代码有很大帮助,即使它们没有提供多线程性能优势。

答案 1 :(得分:0)

multiprocessing.Pool实际上以并行方式运行代码。

文档说明

  

多处理程序包提供本地和远程并发,   通过使用有效地回避了全局解释器锁定   子进程而不是线程。因此,多处理   模块允许程序员充分利用多个处理器   给定的机器。

尝试一下,check the docs以获取更多信息!

from multiprocessing import Pool
import time


def f(n):
    print('start sleeping')
    time.sleep(4)
    print('slept enough')
    return n*2

s = time.time()
with Pool(4) as p:
    r = p.map(f, [1,2,3,4])
print(f'multiprocessing version runtime: {round(time.time()-s,2)} seconds')
print(r)


s = time.time()
r=[]
for n in [1,2,3,4]:
    r.append(f(n))
print(f'loop version runtime: {round(time.time()-s,2)} seconds')
print(r)

输出:

start sleeping
start sleeping
start sleeping
start sleeping
slept enough
slept enough
slept enough
slept enough
multiprocessing version runtime: 4.03 seconds
[2, 4, 6, 8]
start sleeping
slept enough
start sleeping
slept enough
start sleeping
slept enough
start sleeping
slept enough
loop version runtime: 16.01 seconds
[2, 4, 6, 8]