我必须在这里遗漏一些东西但是这个试图修改函数中的全局变量的两个线程的简单例子没有给出预期的结果:
from threading import Thread, Lock
some_var = 0
def some_func(id):
lo = Lock()
with lo:
global some_var
print("{} here!".format(id))
for i in range(1000000):
some_var += 1
print("{} leaving!".format(id))
t1 = Thread(target=some_func, args=(1,))
t2 = Thread(target=some_func, args=(2,))
t1.start()
t2.start()
t1.join()
t2.join()
print(some_var)
输出:
1 here!
2 here!
2 leaving!
1 leaving!
1352010
正如你所看到的那样,两个线程都进入了应该同时锁定的部分,并且增加了globel变量&some; some_var'因此而变得混乱。
看起来Lock由于某种原因不起作用。 对于高达10000的范围,它可以正常工作,但这可能只是因为在这么短的计算过程中没有释放GIL。
发生了什么事?
我使用的是Python3.3.2 64位
答案 0 :(得分:6)
Lock()
函数创建一个全新的锁 - 只有调用该函数的线程才能使用。这就是为什么它不起作用,因为每个线程都锁定一个完全不同的锁。
锁定项目是您可以在没有任何问题的情况下声明为全局的少数事项之一,因为您绝对希望每个线程看到相同的Lock()
。你应该试试这个:
from threading import Thread, Lock
some_var = 0
lo = Lock()
def some_func(id):
global lo
with lo:
global some_var
print("{} here!".format(id))
for i in range(1000000):
some_var += 1
print("{} leaving!".format(id))
答案 1 :(得分:3)
每次调用函数时,都会创建一个新的锁,因此每个不同的线程都有不同的锁。应该全局创建Lock对象,因为每个线程都应该能够看到同一个锁是否被另一个锁占用。尝试将锁定对象创建为全局锁定!
答案 2 :(得分:0)
或者您可以在main()函数中定义锁定。并将其传递给被调用的函数。
lock = threading.Lock()
t1 = Thread(target=some_func, args=(1,lock))
t2 = Thread(target=some_func, args=(2,lock))
t1.start()
t2.start()
这种方式只有一个锁。最好尽可能避免全局变量。