这两段代码(关于python GIL)之间的区别是什么?

这两段代码(关于python GIL)之间的区别是什么?,python,gil,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) before = time() thread1 = Thread(target=get_c

片段代码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)
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)
要运行代码,结果是
5.74065279906323

线程图为:

片段代码2

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)
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

线程图为:

我认为结果会相似。但最终结果并非如此。为什么?
有人能帮我解释一下吗?

for url in urls:
    thread1 = Thread(target=get_content, args=(url,))
    thread1.start()
    thread1.join()
您的
.join
位于
for
循环中,因此它将首先启动并加入,然后再移动到下一个线程。在这之后,您应该有第二个循环来加入它们。

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

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()
这段代码实际上和第二个代码片段一样,只是有一个循环。

线程1.join()等待线程完成。您在循环中已经有了它,这意味着在第一个请求完成之前,循环不会进入下一个迭代

实际上,您已经“扼杀”了多线程思想,并迫使程序一次执行一个请求

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

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)

第一个示例启动一个线程,然后在启动下一个线程之前加入它(等待它完成)。第二个示例启动它们,然后等待它们全部完成。基本上是顺序对并行(或连续对并发)。我从你的问题中删除了gil标记,因为这与gil无关,只是误解了
threadobj.join()
的工作原理。你把它放回去编辑你的标题有什么原因吗?你的答案很有用,非常感谢。你为什么要列出
None
s(只是为了把它扔掉)?@jedwards因为在
t中只使用
[]
。线程中的t的join()不是合法的语法,另一个选项是将它改成两行。我也不想在这里进行优化,只想说明一点。
对于线程中的t:t.join()
可以在一行上,而不创建列表。