在了解线程之间的操作及进程死锁之前先来了解一下什么是进程?以下是官方的解释。
线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。
线程是独立调度和分派的基本单位。线程可以为操作系统内核调度的内核线程,如Win32线程;由用户进程自行调度的用户线程,如Linux平台的POSIX Thread;或者由内核与用户进程,如Windows 7的线程,进行混合调度。
同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。
一个进程可以有很多线程,每条线程并行执行不同的任务。
在多核或多CPU,或支持Hyper-threading的CPU上使用多线程程序设计的好处是显而易见,即提高了程序的执行吞吐率。在单CPU单核的计算机上,使用多线程技术,也可以把进程中负责I/O处理、人机交互而常被阻塞的部分与密集计算的部分分开来执行,编写专门的workhorse线程执行密集计算,从而提高了程序的执行效率。
看着是不是非常的晕,没关系,下面让我们用实例来享受线程带来的舒适。
1、线程之元组传参
# TODO 鸟欲高飞,必先展翅 # TODO 向前的人 :Jhon # TODO 元组 import threading import time def task(count): for i in range(count): print("正在工作") time.sleep(0.2) else: print("工作结束") if __name__ == '__main__': #创建子线条程 task_thred=threading.Thread(target=task,args=(5,)) task_thred.start()
结果
# TODO 字典 import threading import time def task(count): for i in range(count): print("正在工作") time.sleep(0.2) else: print("工作结束") if __name__ == '__main__': #创建子进程 task_thred=threading.Thread(target=task,kwargs={"count":6}) task_thred.start()
因为
结果
2、线程之字典传参
task_thred=threading.Thread(target=task,kwarg={"count":6})创建子线程并将字典{“count”:6}传给task(count)函数,函数中count形参接收。其中target=task,target就是目标,也就是目标函数的意思。字典就类似于json字符串,找个网页单机右键检查找到网络下面的全部,找一个js文件打开(可以不一定是js文件,其他的也可以)刷新一下你就可以发现标头里的都是以字符串显示的
task_thred.start()就是将上面创建的线程开启,注意一定要开启线程,不然线程开启不了程序无法执行。time.sleep(0.2),休眠0.2秒,看起来卡顿卡顿的,更好的看出进程执行的过程
3、线程执行规则
很显然是无序的,线程和进程都是用于资源调度,是随机分配的,所以是都是无序的。下面通过例子来看一下。
# TODO 线程之间执行时无序的 import threading import time def work1(): time.sleep(1) print("当前的线程是:",threading.current_thread().name) if __name__ == '__main__': for _ in range(5): work_thred=threading.Thread(target=work1) work_thred.start()
结果:
第一次执行结果
第二次执行结果:
我们对比两次的执行结果可以发现第一次执行的线程顺序是: 4->5->1->3->2,而蒂维茨执行的县城顺序是: 3->5->2->1->4,很显然两次的执行顺序不一致,所以线程的执行是没有顺序的
4、测试主次线程权限,如何消除权限???又如何巩固主线程的掌控权
测试主线程是否会等待子线程执行完毕关闭,通过下面的例子你可以很好的了解。
# TODO 测试主线程是否会等待子线程执行完毕关闭 import time import threading def show_info(): for i in range(5): print("test,",i) time.sleep(1) if __name__ == '__main__': show_thted=threading.Thread(target=show_info) show_thted.start() time.sleep(1.5) print("结束")
结果:
我们可以发现主线程结束后,子进程也停止了执行,达到预期目的,方法可行。
4.1、方法一:
创建进程的时候加入守护进程daemon
# TODO 测试主线程是否会等待子线程执行完毕关闭 import time import threading def show_info(): for i in range(5): print("test,",i) time.sleep(1) if __name__ == '__main__': show_thted=threading.Thread(target=show_info,daemon=True) show_thted.start() time.sleep(1.5) print("结束")
结果:
我们可以发现主线程结束后,子进程也停止了执行,达到预期目的,方法可行
4.2、方法二
难道必须在创建进程的时候就要放入守护进程吗?
# TODO 测试主线程是否会等待子线程执行完毕关闭 import time import threading def show_info(): for i in range(5): print("test,",i) time.sleep(1) if __name__ == '__main__': show_thted=threading.Thread(target=show_info) show_thted.setDaemon(True) show_thted.start() time.sleep(1.5) print("结束")
结果:
这样是不是也可以确保主线程停止后子线程跟着停止,ok,达到效果,方法可行。但是你们有没有发现这样很多余,明明一行代码就可以实现的,为什么要多行代码执行呢,但是作为一个方法,记住还是很有必要的。