写在前面
python(基于cpython解释器)的多线程其实是假多线程,是单个CPU在多个线程间迅速切换营造出来的‘错觉’,所以Python的多线程适用于IO密集型(进程运行时间大部分花在input与output上),而不适用于CPU密集型(进程运行时间大部分花在计算上)
多线程的概念
多线程即多条顺序执行流 “同时” 执行同一个任务
我们将我们需要某一进程执行的任务比作一桌子菜
单线程就是一个人在一张桌子上吃一道菜
多线程就是多个人在一张桌子上吃同一道菜
Python中的多线程
Python中有两种使用线程的方法:函数式(def)与类式(class)
Python通过thread与threading两个标准库提供对线程的支持
Thread较为简陋,本文将使用Threading进行说明
多说无益,上代码:
单线程示例:
from time import sleep
def Write():
for i in range(3):
print('作家正在写第%d篇文章'%(i+1))
sleep(1) # 加一个休眠,方便观察
def Sing():
for i in range(3):
print('歌手正在唱第%d首歌'%(i+1))
sleep(1)
if __name__ == '__main__':
Write()
Sing()
执行结果:
作家正在写第1篇文章
作家正在写第2篇文章
作家正在写第3篇文章
歌手正在唱第1首歌
歌手正在唱第2首歌
歌手正在唱第3首歌
(耗时大约6秒)
利用threading模块中的Thread方法开启新线程,基本参数如下
threading.Thread(target,args,name)
*target*:需要执行的函数/类名
*arges*:传递给函数/类的参数(需要以列表[]或元祖()的形式)
*name*:该线程的名字(可以随便取)
用.start()启动线程
多线程示例(双线程):
import threading
import time
def Write():
for i in range(3):
print('作家正在写第%d篇文章'%(i+1))
time.sleep(1) # 程序运行到这里休眠一秒,方便观察
def Sing():
for i in range(3):
print('歌手正在唱第%d首歌'%(i+1))
time.sleep(1)
if __name__ == '__main__':
tr1 = threading.Thread(target=Write) # 传入函数名
tr2 = threading.Thread(target=Sing)
tr1.start()
tr2.start()
运行结果:
作家正在写第1篇文章
歌手正在唱第1首歌
作家正在写第2篇文章
歌手正在唱第2首歌
作家正在写第3篇文章
歌手正在唱第3首歌
(耗时大约3秒)
我们说过多线程是多个人在同一张桌子上吃同一道菜
多个人同时吃一道菜的时候容易发生争抢,例如两个人同时夹一个菜,一个人刚伸出筷子,结果伸到的时候已经被夹走菜了。。。此时就必须等一个人夹一口之后,在还给另外一个人夹菜,也就是说资源共享就会发生冲突争抢。
也就是说,多线程在数据量过大的情况下容易出现脏数据
正常数据示例(单线程下):
sum = 0
def sum1():
global sum
for i in range(10000000):
sum += 1
print(sum)
if __name__ == '__main__':
for i in range(2):
sum1()
运行结果:
1000000
2000000
脏数据示例(多线程下):
import threading
sum = 0
def sum1():
global sum
for i in range(10000000):
sum += 1
print(sum)
if __name__ == '__main__':
'''开启两个线程执行sum1'''
for i in range(2):
th = threading.Thread(target=sum1)
th.start()
运行结果: