• python 线程锁


     在多线程中,同一个变量能被所有线程共享,这个变量能被任何一个线程修改。

    看一个实验。

    启动5个线程,每个线程把全局变量加1

    import threading
    import time
    
    t_objs = []
    def run(n):
        global num
        num+=1
    num = 0
    
    for i in range(5):
        t = threading.Thread(target=run,args=("t-%s" %i,))
        t.start()
        t_objs.append(t)
    
    for t in t_objs:
        t.join()
    print('num:',num) #num: 5
    

     启动了5个线程,每个线程加1,一共是5个,所以结果是5没有问题。

    python2.7下执行:

    50个线程,num相加50次,也没有问题。1000个线程相加也是没有问题的。

    尝试相减,启动1000个线程,每个线程减1。

    子线程不等待,主线程等待3s。

    根据GIL同一时间只有一个线程在执行,但是并不能保证数据是正确的。这个现象在其它系统中会出现。

     

    线程1拿到的count = 0; 但是线程1没有执行完就被挂起了。紧接着执行线程2,线程2执行完成,并且把count=1赋值给count。这个时候线程1又继续执行,但是之前的线程因为被挂起,所以数据保存在了寄存器里面,并没有在次取数据,这个时候count还是0。那么线程1执行完count++之后count=1,又赋值给了count。最后count的数值还是1,这个计算并不准确。

    这个怎么保证数据的准确性呢?

    理想的状态下,我们希望启动线程时并行,计算数值时串行。

    这个时候需要用户自己加一个锁,这个锁和GIL无关。这个锁是保证同一时间只有一个线程在修改数据。

    import threading
    import time
    
    t_objs = []
    def run(n):
        lock.acquire() #添加锁
        global num
        num+=1
        lock.release()#释放锁
    num = 0
    lock = threading.Lock() #锁的实例
    for i in range(500):
        t = threading.Thread(target=run,args=("t-%s" %i,))
        t.start()
        t_objs.append(t)
    
    for t in t_objs:
        t.join()
    print('num:',num) #num: 500
    

    可以 验证计算是否是串行,在计算的时候sleep.

    import threading
    import time
    
    t_objs = []
    def run(n):
        lock.acquire() #添加锁
        global num
        num+=1
        time.sleep(1)
        lock.release()#释放锁
    num = 0
    lock = threading.Lock() #锁的实例
    for i in range(5):
        t = threading.Thread(target=run,args=("t-%s" %i,))
        t.start()
        t_objs.append(t)
    
    for t in t_objs:
        t.join()
    print('num:',num) #等待5s num: 5
    

     以上现象在2.X会出现。

  • 相关阅读:
    LeetCode 876. 链表的中间结点
    顺序表的定义及其相关基本操作
    LeetCode 206. 反转链表
    LeetCode 111. 二叉树的最小深度
    LeetCode 700. 二叉搜索树中的搜索
    LeetCode 104. 二叉树的最大深度
    LeetCode 908. 最小差值 I
    LeetCode 728. 自除数
    LeetCode 704. 二分查找
    LeetCode 852. 山脉数组的峰顶索引 (二分)
  • 原文地址:https://www.cnblogs.com/qing-chen/p/7679887.html
Copyright © 2020-2023  润新知