一、多线程共享全局变量:在一个进程内的所有线程共享全局变量,方便在多个线程间共享数据
缺点:线程是对全局变量随意修改可能造成多线程之间对全局变量的混乱(即线程非安全)
# 定义一个全局变量
num=1
def threadA():
'''子线程A执行部分'''
pass
def threadB():
'''子线程执行部分'''
pass
def run():
t1=threading.Thread(target=threadA) #子线程A
t2=threading.Thread(target=threadB) #子线程B
t1.start()
t2.start()
pass
if __name__=='__main__':
run()
二、在创建子线程执行函数传参
# 定义一个全局变量
number=1
def threadA(i):
'''子线程A执行部分'''
print(i)
pass
def threadB(k):
'''子线程执行部分'''
print(k)
pass
def run():
t1=threading.Thread(target=threadA,args=(number,)) #子线程A
t2=threading.Thread(target=threadB,args=(number,))#子线程B
t1.start()
t2.start()
pass
if __name__=='__main__':
run()
注意:args= () 元组, 单个数据时,则必须加上逗号
否则发生异常:TypeError: threadB() argument after * must be an iterable, not int
三、多线程的资源竞争
比如:
同一个房间, 要看电视(全局资源) A用户 中央1台 B用户 中央2台 C用户 中央3台 D用户 中央4台 同一个资源需要竞争问题?
(1)使用单线程:
#全局资源,全局变量
_num=0
def threadA(a):
global _num
for i in range(a):
_num+=1
print(f'单线程中,threadA函数里面,_num的值:{_num}')
def threadB(a):
global _num
for i in range(a):
_num+=1
print(f'单线程中,threadB函数里面,_num的值:{_num}')
#调用
threadA(10000)
threadB(10000)
print(f'最终_num的值:{_num}')
(2)使用多线程:
_num=0
def threadA(a):
global _num
'''子线程A执行部分'''
for i in range(a):
_num+=1
print(f'多线程中,threadA函数里面,_num的值:{_num}')
def threadB(a):
global _num
'''子线程A执行部分'''
for i in range(a):
_num+=1
print(f'多线程中,threadB函数里面,_num的值:{_num}')
def run():
# count=10000
count=1000000
#创建子线程A
t1=threading.Thread(target=threadA,args=(count,))
# 创建子线程B
t2=threading.Thread(target=threadB,args=(count,))
t1.start()
t2.start()
#入口
if __name__=='__main__':
run()
time.sleep(3)
print(f'最终_num的值:{_num}')
总结分析:
连个函数中分别自增10000,多线程好像与单线程一样,没有出现资源竞争问题?
如果将count=1000000(100万)他们会发生何变化呢?
单线程没有发生变化,结果还是2000000
多线程发生变化:
多线程中,thread函数里面,_num的值:1262915
多线程中,thread函数里面,_num的值:1313980
最终_num的值:1313980
为何会导致这个问题呢?最终是1300000,少了700000
原因:多线程切换;
说明:
1) 多线程情况下,同一时刻只有一个线程在执行代码,并切换;
切换回来之后,在什么地方暂停,就在什么地方开始
2) _num+=1
(1)先获取_num的值,先获取全局资源
(2) _num+1获得的结果
(3) 把新获取的值赋给全局资源_num
使用单线程还是使用多线程?
计算密集型 不停的计算单线程 更快 (多线程由于切换,需要不停的计算的情况下)单线程的效率会更高
IO密集型 (文件写或读)单线程,傻傻的等, 多线程的效率会更高. 进行切换.