python学习-进程和线程

python学习-进程和线程,第1张

进程
  • 进程就是 *** 作系统中执行的一个程序, *** 作系统以进程为单位分配存储空间,每一个进程都有自己的地址空间、数据栈以及其他用于跟踪进程执行的辅助数据。


    *** 作系统管理所有进程的执行,为进程合理分配资源。


    进程可以通过fork或spawn的方式来创建新的进程来执行其他的任务,不过新的进程也有自己独立的内存空间,因此必须通过进程间通信机制(IPC,Inter-Process Communication)来实现数据共享,具体的方式包括管道、信号、套接字、共享内存区等。


  • 线程就是一个进程中多个并发的执行线索,拥有多个可以获得CPU调度的执行单元。


    线程相比于进程,因为线程在同一个进程下,他们之间共享上下文,所以线程间的信息共享和通信更加容易。


    在单核的cpu种并发是不能真正的实现,在具体的时刻能够获得CPU的只有唯一的一个线程,他们是时间共享CPU。


    通过任务管理器就可以看到进程。


    Python支持多进程又支持多线程,因此使用Python实现并发编程主要有3种方式:多进程、多线程、多进程+多线程

python中的多进程

Unix和Linux *** 作系统上提供了fork()系统调用来创建进程,调用fork()函数的是父进程,创建出的是子进程,子进程是父进程的一个拷贝,但是子进程拥有自己的PID。


fork()函数非常特殊它会返回两次,父进程中可以通过fork()函数的返回值得到子进程的PID,而子进程中的返回值永远都是0。


Python的os模块提供了fork()函数。


由于Windows系统没有fork()调用,因此要实现跨平台的多进程编程,可以使用multiprocessing模块的Process类来创建子进程,而且该模块还提供了更高级的封装,例如批量启动进程的进程池(Pool)、用于进程间通信的队列(Queue)和管道(Pipe)等。


举个例子:

这个例子运行时时一个一个方法执行,我们用多进程的方法来使用。


from multiprocessing import Process
from os import getpid
from random import randint
from time import time, sleep


def download_task(filename):
    print('启动下载,进程号[%d].' % getpid())
    print('开始下载%s...' % filename)
    time_download = randint(5, 10)
    sleep(time_download)
    print('%s下载完成! 耗费了%d秒' % (filename, time_download))


def main():
    start = time()     
    p1 = Process(target=download_task, args=('如何勾搭九亿少女.pdf', )) ##进程一 target传入一个该进程要执行的函数 args是元组,给函数传递参数
    p1.start()  ###开始进程1
    p2 = Process(target=download_task, args=('如何迷倒少男.txt', ))   ##进程二
    p2.start()     ##开始进程2
    p1.join()      #join 等待进程结束
    p2.join()
    end = time()
    print('总共耗费了%.2f秒.' % (end - start))


if __name__ == '__main__':
    main()

用多线程的方法可以观察到现象是两个任务一起开始,时间是两个任务中用时最长的一个。



还可以用subprocess模块中的类和函数来创建和启动子进程,这个自行学习。


python中多线程

多线程开发使用threading模块,该模块的多线程编程提供了更好的面向对象的封装。


再将上面进程的例子实现一次。


from random import randint
from threading import Thread
from time import time,sleep


def download(filename):
    print('开始下载%s。


'% filename) time_download=randint(5,10) sleep(time_download) print('%s 完成下载 耗时%d '%(filename,time_download)) def main(): start =time() t1=Thread(target=download,args=('如何迷倒九亿少女.pdf')) t1.start() t2 = Thread(target=download, args=('如何勾搭少男.txt')) t2.start() t1.join() t2.join() end=time() print('种耗时%s'% (end-start)) if __name__=='__main__': main()

线程还可以自定义哦,用继承的形式,自定义一个类,让它继承Thread类

from random import randint
from threading import Thread
from time import time, sleep

class Download(Thread):       ##继承Thread类
	def __init__(self,filename):
		super().__init__()
		self.filename=filename
  def run(self):
  	print('开始下载%s' % self.filename')
  	time_download=randint(5,10)
  	sleep(time_download)
  	print('%s下载完成 耗费了%d秒’ %(self.filename,time_download)
  	
def main():
    start = time()
    t1 = DownloadTask('Python从入门到住院.pdf')
    t1.start()
    t2 = DownloadTask('Peking Hot.avi')
    t2.start()
    t1.join()
    t2.join()
    end = time()
    print('总共耗费了%.2f秒.' % (end - start))


if __name__ == '__main__':
    main()

线程可以共享进程空间,要实现对各线程间的通向简单一点,可用全局变量(资源)来共享给多线程。


但是这样有可能产生不可控的结果导致程序失效或崩溃,像这样的资源称为临界资源。


对临界资源的访问要加上保护,否则资源会处于“混乱”的状态。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/569452.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-09
下一篇 2022-04-09

发表评论

登录后才能评论

评论列表(0条)

保存