这两段代码有什么区别(大约 python GIL)?

What is the difference between there two sections of code(about python GIL)?

片段代码1:

before = time()
urls = ['https://google.com'] * 5
for url in urls:
    thread1 = Thread(target=get_content, args=(url,))
    thread1.start()
    thread1.join()
after = time()
print(after - before)

到运行的代码,结果是5.740652799606323
线程图是: image link

片段代码2:

before = time()
thread1 = Thread(target=get_content, args=('https://google.com',))
thread2 = Thread(target=get_content, args=('https://google.com',))
thread3 = Thread(target=get_content, args=('https://google.com',))
thread4 = Thread(target=get_content, args=('https://google.com',))
thread5 = Thread(target=get_content, args=('https://google.com',))
thread1.start()
thread2.start()
thread3.start()
thread4.start()
thread5.start()
thread1.join()
thread2.join()
thread3.join()
thread4.join()
thread5.join()
after = time()
print(after - before)

转运行代码,结果为:1.102950096130371
线程图是: image link

我想结果会差不多。但是最后的结果不是。为什么?
谁能帮我解释一下?

for url in urls:
    thread1 = Thread(target=get_content, args=(url,))
    thread1.start()
    thread1.join()

您的 .joinfor 循环中,因此它会先开始并加入,然后再转到下一个线程。在那之后你应该有第二个循环来加入他们。

在第一个代码段中,您 实际上是先 等待每个线程完成,然后再启动另一个线程。你基本上运行它串行而不是并行

for url in urls:
    thread1 = Thread(target=get_content, args=(url,))
    thread1.start()
    thread1.join()

在使用线程时,您可能想要做的是将每个线程保存在一个容器(列表)中,启动所有线程,然后等待所有线程完成。

ths = []
for url in urls:
    thread1 = Thread(target=get_content, args=(url,))
    thread1.start()
    ths.append(thread1)

for t in ths:
    t.join()

这段代码实际上做了你第二个片段所做的,只是有一个循环。

thread1.join() 等待线程完成。你在循环中有它,这意味着循环不会进入下一次迭代,直到第一个请求完成。

基本上你有 "killed" 多线程的想法并强制程序一次执行一个请求。

一种改变的方法是做这样的事情:

before = time()
urls = ['https://google.com'] * 5
threads = []
for url in urls:
    thread1 = Thread(target=get_content, args=(url,))
    thread1.start()
    threads.append(thread1)
[t.join() for t in threads]
after = time()
print(after - before)