【Python3 爬虫】U25_多线程爬虫之多线程共享全局变量及锁机制
1.共享全局变量
1.1 共享全局变量问题
在一个进程内的所有线程共享全局变量,很方便在多个线程之间共享数据,但是存在一个缺点,当线程无序执行的时候,会导致全局变量的混乱,导致数据错误。
例如:
假设两个线程t1和t2都要对全局变量g_num(默认是0)进行加1运算,t1和t2都各对g_num加10次,g_num的最终的结果应该为20。
但是由于是多线程同时操作,有可能出现下面情况:
- 在g_num=0时,t1取得g_num=0。此时系统把t1调度为"sleeping"状态,把t2转换为"running"状态,t2也获得g_num=0
- 然后t2对得到的值进行加1并赋给g_num,使得g_num=1
- 然后系统又把t2调度为”sleeping”,把t1转为”running”。线程t1又把它之前得到的0加1后赋值给g_num。
- 这样导致虽然t1和t2都对g_num加1,但结果仍然是g_num=1
1.2 示例
import threading
num = 0
def get_num():
global num
for i in range(1000000):
num += 1
print("num的值为:%d" %num)
def main():
# 启动2个线程对执行函数get_num
for x in range(2):
t = threading.Thread(target=get_num)
t.start()
if __name__ == '__main__':
main()
本次执行结果:(每次执行结果都不一样)
num的值为:1104111
num的值为:1185898
从上述结果可以看到,两次的和按照常理来说应该是2000000,但实际却不是,说明出现了线程安全问题。
3.锁机制
对于上述问题,结论是:如果多个线程同时对同一个全局变量操作,会出现资源竞争问题,从而数据结果会不正确
那么如何来解决这个问题呢?
我们可以将上述函数的调用加上一把锁,比如线程1准备执行这个函数,那么先把这个函数锁起来,此时,就不允许其他线程来操作,如果要操作,不好意思,得等我执行完,不然,没门。这样就可以保证每次执行函数的时候,全局变量不会同时被2个线程拿到,就解决了资源争夺问题了。下面是具体的代码示例:
import threading
num = 0
g_lock = threading.Lock()
def get_num():
global num
g_lock.acquire()
for i in range(1000000):
num += 1
g_lock.release()
print("num的值为:%d" %num)
def main():
# 启动2个线程对执行函数get_num
for x in range(2):
t = threading.Thread(target=get_num)
t.start()
if __name__ == '__main__':
main()
执行结果:
num的值为:1000000
num的值为:2000000
作者:奔跑的金鱼
声明:书写博客不易,转载请注明出处,请支持原创,侵权将追究法律责任
个性签名:人的一切的痛苦,本质上都是对自己无能的愤怒
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!