一、共享可变类型参数
可变类型(列表、字典、可变集合)
要共享的是可变类型参数,直接将该参数当作实参通过args传入线程中去,其中sleep函数的作用是降低运行速度,方便打印出想要的结果
import threading
from time import sleep
def demo1(a,num):
sleep(0.5)
#为a增加元素
for i in range(num):
a.append(i)
print('demo1的a:{}'.format(a))
def demo2(a,num):
sleep(0.5)
#为a增加元素
for i in range(num):
a.append(i*2)
print('demo2的a:{}'.format(a))
def main():
#创建两个参数
a=[11,22,33]
num=8
#创建两个线程,并将两个参数传递给指定的函数
threading.Thread(target=demo1,args=(a,num)).start()
threading.Thread(target=demo2, args=(a,num)).start()
#打印线程数
print(threading.enumerate())
sleep(1)
print('主线程的a:{}'.format(a))
if __name__ =='__main__':
main()
打印结果:
可以看到最后的结果是两个线程内的计算都进行了的,即同一进程下线程是共享变量的。
二、共享不可变类型参数
不可变类型(数字、字符串、元组、不可变集合)
要共享的是不可变类型参数,不能直接将该参数当作实参通过args传入线程中去,需要在进程执行前创建不可变类型的参数,并且在线程中对其进行修改时需要申明全局变量。
import threading
from time import sleep
def demo1(num):
'''a+100'''
sleep(0.5)
for i in range(num):
global a
a +=1
print('demo1的a:{}'.format(a))
def demo2(num):
'''a+100'''
sleep(0.5)
for i in range(num):
global a
a +=1
print('demo2的a:{}'.format(a))
def main():
#创建一个参数
num=100
#创建两个线程,并将参数传递给指定的函数
threading.Thread(target=demo1,args=(num,)).start()
threading.Thread(target=demo2, args=(num,)).start()
#打印线程数
print(threading.enumerate())
sleep(1)
print('主线程的a:{}'.format(a))
if __name__ =='__main__':
#创建不可变类型的参数
a=0
main()
打印结果:
三、互斥锁(共享过程中碰到的问题)
当 参数a 加100,加200时,没有碰到问题,加10000000,加两千呢?上代码,直接将num改成10000000 ,此时的运行结果:
原因:多线程共享全局变量会出现资源竞争
解决方法:使用互斥锁,一个线程使用锁时,另一个线程就不能对锁中的对象进行操作,直到解锁后,才能对锁中的对象进行操作。
import threading
from time import sleep
def demo1(num,mutex):
'''对数据进行操作'''
for i in range(num):
global a
#锁定
mutex.acquire()
#对数据进行处理
a +=1
#解锁
mutex.release()
print('demo1的a:{}'.format(a))
def demo2(num,mutex):
'''对数据进行操作'''
for i in range(num):
global a
# 锁定
mutex.acquire()
# 对数据进行处理
a += 1
# 解锁
mutex.release()
print('demo2的a:{}'.format(a))
def main():
#创建一个互斥锁,默认没有上锁
mutex=threading.Lock()
#创建一个参数
num=10000000
#创建两个线程,并将参数传递给指定的函数
threading.Thread(target=demo1,args=(num,mutex)).start()
threading.Thread(target=demo2, args=(num,mutex)).start()
#打印线程数
print(threading.enumerate())
sleep(10)
print('主线程的a:{}'.format(a))
if __name__ =='__main__':
#创建不可变类型的参数
a=0
main()
从上面可以看到其实互斥锁就是调用了一个threading下的lock函数
#创建一个互斥锁,默认没有上锁 mutex=threading.Lock() # 锁定 mutex.acquire() # 对数据进行处理 a += 1 # 解锁 mutex.release()
打印结果: