我对python完全陌生,当我遇到此问题时,我正在尝试线程化模块: -线程由于某种原因运行两次,我不知道为什么。我到处搜索,但找不到任何答案。 希望我能在这里得到一些帮助
import time
from threading import Thread
import requests as requests
import threading as threading
threads = []
i = 0
time.sleep(0.5)
def whatever():
global i
while i < 10:
get = requests.get("http://www.exemple.com")
print(i)
i += 1
for t in range(5):
t = threading.Thread(target=whatever)
threads.append(t)
t.start()
我想要什么:
0
1
2
3
4
5
6
7
8
9
10
11
12
13
输出:
0
1
1
3
4
5
6
7
7
9
10
11
12
13
答案 0 :(得分:0)
从多个线程修改全局变量本质上是不安全的。您需要锁定访问权限以防止出现竞争状况,例如线程A读取i
,然后线程B运行并递增i
并将其存储回去,然后线程A再次进入并存储其递增的副本i
,因此它不会递增两次,而只会递增一次。
解决方法是锁定访问权限,或者提出一种天生的线程安全的方式来执行所需的操作。在CPython参考解释器上,可以确保在字节码之间不释放任何GIL,因此有一些技巧可以在没有锁定的情况下进行:
import time
from threading import Thread
threads = []
igen = iter(range(10))
time.sleep(0.5)
def whatever():
for i in igen:
get = requests.get("http://www.exemple.com")
print(i)
for t in range(5):
t = threading.Thread(target=whatever)
threads.append(t)
t.start()
使用锁更为复杂,但应可移植到任何具有可预测的(行为,毕竟仍在线程化)行为的Python解释器中:
import time
from threading import Thread, Lock
threads = []
i = 0
ilock = Lock()
time.sleep(0.5)
def whatever():
global i
while True:
with ilock:
if i >= 10:
break
icopy = i
i += 1
get = requests.get("http://www.exemple.com")
print(icopy)
for t in range(5):
t = threading.Thread(target=whatever)
threads.append(t)
t.start()
这不会按数字顺序打印出来,但是它将并行运行请求,并且只会打印一次i
的任何给定值。