zoukankan      html  css  js  c++  java
  • 【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

  • 相关阅读:
    【强烈推荐】 超漂亮的仿腾讯弹出层效果(兼容主流浏览器<转>;
    必须掌握的八个【cmd 命令行】
    grep命令的用法
    sed 命令的用法1
    Paste命令的用法
    uniq命令的用法
    join命令的用法
    Sort命令的用法
    cut命令的用法
    tr命令学习
  • 原文地址:https://www.cnblogs.com/OliverQin/p/12632095.html
Copyright © 2011-2022 走看看