参考博客:
https://www.cnblogs.com/melonjiang/p/5307705.html
https://blog.csdn.net/u013210620/article/details/78723704
1、python2与python3在多线程中,在不加锁的情况下对共享数据的修改的问题:
示例代码:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import threading
import time
num = 100 #设置一个共享变量
def show():
global num #在函数内操作函数外变量,需设置为全局变量
time.sleep(1)
num -= 1
list=[]
for i in range(100):
t = threading.Thread(target=show)
t.start()
list.append(t)
for t in list:
t.join()
print(num)
在python2中,上述代码有时候输出0(正常情况),有时候输出1,2,3,10等等不正确的数。
而在python3中,全部输出正常(输出0)
2、使用lock锁:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import threading
import time
num = 100 #设置一个共享变量
lock=threading.Lock() #生成全局锁
def show():
global num #在函数内操作函数外变量,需设置为全局变量
time.sleep(1)
lock.acquire() #修改前加锁
num -= 1
lock.release() #修改后解锁
list=[]
for i in range(100):
t = threading.Thread(target=show)
t.start()
list.append(t)
for t in list:
t.join()
print(num)
3、使用递归锁Rlock锁:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import threading
#递归锁
def run1():
lock.acquire() #小锁
global num
num +=1
lock.release()
return num
def run2():
lock.acquire() #小锁
global num2
num2+=1
lock.release()
return num2
def run3():
lock.acquire() #大锁
res = run1()
res2 = run2()
lock.release()
print(res,res2)
if __name__ == '__main__':
num,num2 = 0,0
lock = threading.RLock() #生成Rlock
for i in range(10):
t = threading.Thread(target=run3)
t.start()
while threading.active_count() != 1:#如果不等于1,说明子线程还没执行完毕
pass #打印进程数
else:
print(num,num2)
4、lock和Rlock的区别:
RLock允许在同一线程中被多次acquire。而Lock却不允许这种情况。 如果使用RLock,那么acquire和release必须成对出现,即调用了n次acquire,必须调用n次的release才能真正释放所占用的琐。
import threading
lock = threading.Lock() #Lock对象
lock.acquire()
lock.acquire() #产生了死琐。
lock.release()
lock.release()
import threading
rLock = threading.RLock() #RLock对象
rLock.acquire()
rLock.acquire() #在同一线程内,程序不会堵塞。
rLock.release()
rLock.release()
5、何时使用递归锁:
为了支持在同一线程中多次请求同一资源,python提供了"递归锁":threading.RLock。RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次acquire。直到一个线程所有的acquire都被release,其他的线程才能获得资源。