许女士
Python之线程
来源:银国玉     发布时间: 2019-05-05      浏览次数:71

字号:

一、线程的起源

  1,进程

  之前我们已经了解了操作系统中进程的概念,程序并不能单独运行,只有将程序装载到内存中,系统为其分配资源才能运行,而这种执行的程序就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本;进程是程序的一次活动,属于动态概念。在多道编程中,我们允许多个程序同时加载到内存中,在操作系统的调度下,可以实现并发的执行。这样的设计大大提高了CPU的利用率。

  2,为什么还出现线程

  例子:pycharm三个任务:键盘输入、屏幕输出、自动保存硬盘,如果三个任务是同步工作的,那在键盘输入的时候我们就看不到屏幕输入,而我们需要在键盘输入的时候同时在屏幕上显示,还能在硬盘保存。方案一,此时我们可以开三个进程来完成,三个进程之间还要通过进程通信的介质帮助完成。方案二,其实我们还可以用线程来完成,此时我们可以在一个进程中开三个线程,由于线程间是资源共享的,所以不用借助介质就能完成数据交换。我们对比两种方案,方案一要开三个进程,如果有10000个任务,那就要开10000个进程,开进程很占内存的,而且开进程很耗时间的,还要借助介质才能实现通信,而方案就不一样了,只需开一个进程,节省了内存空间,缩短了时间,自身就可以实现数据共享,那肯定选择方案二,从而就凸显了线程的必要性。

  3,线程的出现

  随着计算机技术的发展,进程出现了很多弊端,一是由于进程是资源拥有者,创建、撤销与切换存在较大的时空开销,因此引入轻型进程;二是由于对称多处理机出现,可以满足多个运行单位,二多个进程并行开销过大,出现了能独立运行的基本单位——线程,进程是资源分配的最小单位,线程是CPU调度的最小单位,每个进程中至少有一个线程,进程只是把资源集中到一起,而线程才是CPU上的执行单位。

  4,线程与进程的关系

  线程就是进程的组成单元,每一个进程至少有一个线程,同一个进程里的多个线程,可以共享进程里的资源,而且线程间切换比进程间切换快很多,进程不是一个可执行的实体,真正去执行程序的是线程,可以理解进程解释装线程的容器。

二,线程的创建方法

  由于线程诞生于进程,所以说线程的创建和进程一模一样,只是引用的模块不一样而已。

  1,方法一

from threading import Thread #和进程相比,就是线程引入的是Thread模块def fun1(i): print("你是%s"%(i))if __name__ == "__main__": t=Thread(target=fun1,args=(1,)) t.start() print("dddddddd")

  2,方法二

from threading import Threadclass Mythread(Thread): def __init__(self,nn): super().__init__() self.nn=nn def run(self): print("nishi%s"%self.nn)if __name__ == "__main__": t=Mythread("haha") t.start() print("dfssd")

三、多进程与多线程的效率对比

from multiprocessing import Processfrom threading import Threadimport timedef fun(): print("ffff")if __name__ == "__main__": l1=[] t_s_t=time.time() for i in range(100): t=Thread(target=fun,) l1.append(t) t.start() [tt.join() for tt in l1] t_e_t=time.time() l2 = [] p_s_t = time.time() for i in range(100): p = Process(target=fun, ) l1.append(p) p.start() [pp.join() for pp in l2] p_e_t = time.time() print("线程",t_e_t-t_s_t) print("进程",p_e_t-p_s_t)

线程 0.04086899757385254进程 3.268401861190796

  从上面的结果看,线程的效率比进程高很多,这主要是创建、销毁进程和进程间切换太耗时间。

四、线程的其他方法

from threading import Thread,current_threadimport threading,timedef fun(i): time.sleep(2) print("我是%s号"%i) print("%s"%current_thread().getName()) #获取线程的name print("%s"%current_thread().ident) #获取线程的idif __name__ == "__main__": for i in range(10): t=Thread(target=fun,args=(i,)) t.start() print(threading.enumerate()) #返回一个正在运行线程的列表 print(threading.active_count()) #返回正在运行线程的数量

五、死锁现象

from threading import Thread,Lock,RLockimport timedef fun(loa,lob): loa.acquire() time.sleep(1) print("aaaaa") lob.acquire() print("bbbbb") lob.release() loa.release()def fun1(loa,lob): lob.acquire() time.sleep(1) print("cccccc") loa.acquire() print("ddddd") loa.release() lob.release()if __name__ == "__main__": # loa=Lock() #当我们用Lock时就会出现死锁现象,由于是异步执行的,fun1拿到loa,fun2拿到lob,然后fun1再去拿lob,fun2再去拿loa,但现在两把锁都被对方拿着,还没释放,从而形成死锁 # lob=Lock() loa=lob=RLock() #当我们用Rlock时,若fun1先抢到,就必须等fun1用完,fun2才能拿到,这称为递归锁 t1=Thread(target=fun,args=(loa,lob)) t2=Thread(target=fun1,args=(loa,lob)) t1.start() t2.start()

六、主进程和主线程的结束标志

  主进程在主进程的代码执行完就结束,而主线程要等到在同一进程中的非守护线程代码执行完毕才结束。

主进程的结束标志from multiprocessing import Processimport timedef fun1(): time.sleep(2) print("我是fun1")def fun2(): time.sleep(3) print("我是fun2")if __name__ == "__main__": p1=Process(target=fun1,) p2=Process(target=fun2,) p1.daemon=True #p1现在是守护进程,在主进程结束后,随之结束 p1.start() p2.start() print("我是主进程") #主进程会在这句代码执行完后结束,p1也会跟着结束,虽说p1还没执行完,但是p1直接被干死了结果如下

我是主进程我是fun2

 

主线程结束标志from threading import Threadimport timedef fun1(): time.sleep(2) print("我是fun1")def fun2(): time.sleep(3) print("我是fun2")if __name__ == "__main__": t1=Thread(target=fun1,) t2=Thread(target=fun2,) t1.daemon=True #把t1设为守护线程 t1.start() t2.start() print("我是主线程") #这句代码执行完后,主线程还没结束,主线程要等待非守护线程t2执行完毕后才结束,因为t2执行时间比t1长,所以这次t1也会执行完毕

 

, 1, 0, 9);

  • 相关内容: