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会出现。

原文地址:https://www.cnblogs.com/qing-chen/p/7679887.html