博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
threading多线程模块
阅读量:6000 次
发布时间:2019-06-20

本文共 5421 字,大约阅读时间需要 18 分钟。

1 基本实现

Thread(target=函数名,args=(以元组形式传递的实参,要加","))

th = threading.Thread(target=run,args=(i,))就是实例化一个线程

th.start()就是对实例调用启动函数。

在内部,主线程就会创建30个子线程,子线程并发执行,所以虽然每个线程sleep(3),但是是并发执行的。

进程总耗时3s出头。

import timeimport threadingdef run(arg):    print('run %s' %(arg))    time.sleep(3)for i in range(30):    th = threading.Thread(target=run,args=(i,))    th.start()

 

2 深入理解线程

2.1 主线程和子线程

程序执行时,产生一个进程,进程里首先有一个主线程,每个执行的是子线程

使用threading.current_thread(),发现在for循环中是主线程,在run函数里是子线程。

import timeimport threadingdef run(arg):    print('run %s' %(arg))    time.sleep(3)for i in range(3):    th = threading.Thread(target=run,args=(i,))    print(threading.current_thread())    th.start()>>>><_MainThread(MainThread, started 13112)>run 0<_MainThread(MainThread, started 13112)>run 1<_MainThread(MainThread, started 13112)>run 2

  

import timeimport threadingdef run(arg):    print('run %s' %(arg))    print(threading.current_thread())    time.sleep(3)for i in range(3):    th = threading.Thread(target=run,args=(i,))    th.start()>>>>run 0
run 1
run 2

  

2.2 子线程的并发性

cost_time的打印值:cost time 0.07500743865966797

发现没有在上面的for循环结束后再执行cost_time = time.time() - start_time语句。

因为每个实例化线程就是创建子线程,创建完后子线程自己去运行。主线程马上进入下一个执行语句,不会等待子线程执行完毕。

import timeimport threadingdef run(arg):    print('run %s' %(arg))    time.sleep(10)start_time = time.time()for i in range(600):    th = threading.Thread(target=run,args=(i,))    th.start()cost_time = time.time() - start_timeprint('cost time', (cost_time))

 

3 JOIN()

就是wait函数,一个线程调用join(),主线程就会等子线程执行完毕再往下走.

在这个程序中,相当于线程单并发顺序执行。

import timeimport threadingdef run(arg):    print('run %s' %(arg))    time.sleep(1)start_time = time.time()for i in range(10):    th = threading.Thread(target=run,args=(i,))    th.start()    th.join()cost_time = time.time() - start_timeprint('cost time', (cost_time))

>>>

E:\Python\2018L1\venv\Scripts\python.exe E:/Python/2018L1/test/threadingserver.pyrun 0run 1run 2run 3run 4run 5run 6run 7run 8run 9cost time 10.010000944137573

  

创建空列表t_list,然后把线程实例作为元素追加到列表(不在这里写join,不然会在每个线程中顺序sleep。)

在一个for循环里,让每个实例执行join()。

最后cost time 3.002300262451172

import timeimport threadingdef run(arg):    print('run %s' %(arg))    time.sleep(3)start_time = time.time()t_list = []for i in range(10):    th = threading.Thread(target=run,args=(i,))    th.start()    t_list.append(th)for i in t_list:    i.join()cost_time = time.time() - start_timeprint('cost time', (cost_time))

  

4 setDaemon

当主线程退出,守护子线程不管有没有执行完毕,都会马上退出。

对于非守护子线程,主线程会等它执行完毕再退出。

对于守护线程,主线程不会等它执行完毕,而是直接退出。

 

4.1

以下程序,虽然没有join函数,但主线程也会在所有线程执行完毕后才退出。

import timeimport threadingdef run(arg):    print('run %s' %(arg))    time.sleep(3)    print(threading.current_thread())for i in range(3):    th = threading.Thread(target=run,args=(i,))    #th.setDaemon(True)    th.start()

 

 

4.2

如果把子线程都设置为守护线程,就是说主线程不会在它执行完毕再退出,而是直接退出。

print(threading.current_thread())还没执行,就已经退出,不会再执行

import timeimport threadingdef run(arg):    print('run %s' %(arg))    time.sleep(3)    print(threading.current_thread())for i in range(3):    th = threading.Thread(target=run,args=(i,))    th.setDaemon(True)    th.start()

  

4.3

主线程的执行时间比守护子线程长。在主线程退出前子线程已执行完毕。

import timeimport threadingdef run(arg):    print('run %s' %(arg))    time.sleep(3)    print(threading.current_thread())for i in range(3):    th = threading.Thread(target=run,args=(i,))    th.setDaemon(True)    th.start()time.sleep(4)

  

5 GIL全局解释器锁

在cpython上,使用gil(global interpreter lock),来保证同一时间只有一个线程在解释器中运行。所有的线程并发都是通过context switch来完成。

这使得python无法真正使用多核cpu。

 

6 线程锁(互斥锁)

6.1 线程共享数据池

在进程中的多线程,共享进程的内存空间。就是可以对同一个数据进行操作

import timeimport threadingnum = 0def run():    global num  #函数使用全局变量,需要global声明    time.sleep(2)    num += 1    print('thread:',num)for i in range(20):    th = threading.Thread(target=run)    th.start()time.sleep(5)print(num)

  

6.2 线程锁的作用

多个线程同时操作同一块数据,假设t1先拿到data = 0,然后使用解释器,调用cpu运算 data ++。还没运算完成,就被context switch。

这时t2也操作data,这是data = 0,然后使用解释器,调用cpu运算data ++,然后把data = 1写入data数据。

这时切换回t1,t1从context里拿到数据data = 0,运算完成,然后把data = 1写入data数据。

这样就出错了。

所以需要对data这块数据上锁,同一时间只能有一个线程进行操作。

python3上程序会自动加锁。

 

6.3 死锁和递归锁

https://blog.csdn.net/u013210620/article/details/78723704

用得着再看

 

6.4 信号量

同一时间有几个线程可以访问共享数据。

信号量就是多把锁,允许同时多个线程运行。

可以控制同一时刻可以运行的线程数。

 

7 Event事件

用于实现线程间通信

set表示设定标志位,clear是清空标志位,在处理标志位的函数体中

wait是等待标志位为set,is_set是判断标志位是否为set,在检测标志位的函数体中

import timeimport threadingevent = threading.Event()#-----红绿灯函数,在红灯时标志位清零,绿灯设置标志位-----def lighter():    count = 0    event.set()    while True:        count += 1        time.sleep(1)        if count > 20 and count <= 30:            event.clear()   #20-30s,红灯            print('\33[41mred light on\33[0m')        elif count > 30:            event.set()            count = 0        else:            print('\33[42mgreen light on\33[0m')#----汽车函数,红灯停绿灯行,每秒1km----def car(name):    global mileage    while True:        if event.is_set():            mileage += 1            time.sleep(1)            print('%s is running,the mileage is %s kilometer' % (name,mileage))        else:            time.sleep(1)            print('%s is wait' %(name))            event.wait()    #等待标志位设为setif __name__ == '__main__':    mileage = 0    car1 = threading.Thread(target=car,args=('本田车',))    car1.start()    light = threading.Thread(target=lighter,)    light.start()

  

 8 应用场景

python是伪多线程,实际上是单线程在context switch,所以不适合cpu密集型操作任务,而适合io密集型任务。(socket的多并发网络连接就是io密集型任务)

转载于:https://www.cnblogs.com/jabbok/p/9051619.html

你可能感兴趣的文章
poj2828 线段树
查看>>
二叉树
查看>>
洛谷⑨月月赛Round2 P3393逃离僵尸岛[最短路]
查看>>
群晖NAS使用Docker安装迅雷离线下载出现the active key is not valid.
查看>>
spring boot 2使用Mybatis多表关联查询
查看>>
《数字图像处理》冈萨雷斯学习笔记3:频域处理
查看>>
Making HTTP requests via telnet - Tony's Place
查看>>
千元机市场再添“新宠”,红米Note7和vivo Z3谁才是千元王者
查看>>
荣耀10GT升级EMUI 9.0体验分享:这可能是最好用的手机操作系统
查看>>
ZStack基于华芯通打造ARM国产云平台 助力云上贵州多项应用
查看>>
SACC 2018:容器专场的回顾与总结
查看>>
七年相爱相杀:九张图带你了解苹果MacBook的老对手
查看>>
OKI图文9系LED帮您轻松搞定不干胶打印
查看>>
天津海关2018年共监管中欧班列出口81列、7329标箱
查看>>
春运里的机场行李装卸工 每人每天分拣千余件
查看>>
200本“保护日记”记录黄山迎客松生长变化
查看>>
多方力量携手呵护“中华水塔”青海三江源
查看>>
互联网的下一波红利在哪里?
查看>>
拿姐姐身份证登记结婚竟然成了!婚姻户籍信息共享难在哪儿
查看>>
恒大造车加速,联手柯尼塞格打造顶级新能源车
查看>>