同一个进程的内多个线程可以同时访问和修改同一个数据, 这样的数据我们一般称之为共享资源.
资源共享的问题
下面我们用多个线程去访问同一个资源:
from threading import *
import time
num = 100 # 定义一个变量, 表示共享资源
def foo():
global num
for i in range(100):
if num > 0: # num值不允许是负数
time.sleep(0.3)
num = num - 1
print(current_thread().name, num)
for i in range(6):
t = Thread(target=foo, name="子线程 %d" % i)
t.start()
说明:
虽然我们中代码中限制了num
不会小于0
,但是由于多个线程同时修改了共享资源, 导致出现了不应该出现的合理情况.
原因:
假设现在num == 1, 假设线程0 的if
运行之后, 进入了线程休眠,然后线程1(或者其他线程)也进来了, 那么num仍然是1, 然后休眠.
这个时候线程0休眠结束了, 把num
变成0
. 然后线程0就会结束了.这个时候线程1休眠结束了, 会从刚才休眠的地方继续执行, 然后把num
变成了-1
....
Lock
对象
如何解决上面的问题?
如果有线程的if
为true, 在这个线程离开if语句之前, 则不应该有其他线程进到if
语句中.
python提供了一种叫做Lock
的锁来实现这种需求.
from threading import *
import time
num = 100 # 定义一个变量, 表示共享资源
# 创建一个锁, 用这把锁去锁定共享资源,只有抢到这个把锁的线程才可以修改共享资源
lock = Lock()
```python
def foo():
global num, lock
for i in range(100):
lock.acquire() # 获取到锁
try:
if num > 0: # num值不允许是负数
num = num - 1
print(current_thread().name, num)
finally:
lock.release() # 一定要释放锁, 所以把释放锁的代码放在finally中
for i in range(6):
t = Thread(target=foo, name="子线程 %d" % i)
t.start()