千锋教育-做有情怀、有良心、有品质的职业教育机构

Python学习之进程和线程

来源:千锋教育
发布时间:2023-11-06 01:18:56
分享

对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程,打开一个Word就启动了一个Word进程。

有些进程还不止同时干一件事,比如Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)。

进程

Python的os模块封装了常见的系统调用,其中包括fork,可以在Python程序中轻松创建子进程:

importos

print('Process(%s)start...'%os.getpid())

#OnlyworksonUnix/Linux/Mac:

pid=os.fork()

ifpid==0:

print('Iamchildprocess(%s)andmyparentis%s.'%(os.getpid(),os.getppid()))

else:

print('I(%s)justcreatedachildprocess(%s).'%(os.getpid(),pid))

运行结果如下:

Process(876)start...

I(876)justcreatedachildprocess(877).

Iamchildprocess(877)andmyparentis876.

由于Windows没有fork调用,上面的代码在Windows上无法运行。由于Mac系统是基于BSD(Unix的一种)内核,所以,在Mac下运行是没有问题的,推荐大家用Mac学Python!

multiprocessing

如果你打算编写多进程的服务程序,Unix/Linux无疑是正确的选择。由于Windows没有fork调用,难道在Windows上无法用Python编写多进程的程序?

由于Python是跨平台的,自然也应该提供一个跨平台的多进程支持。multiprocessing模块就是跨平台版本的多进程模块。

multiprocessing模块提供了一个Process类来代表一个进程对象,下面的例子演示了启动一个子进程并等待其结束:

frommultiprocessingimportProcess

importos

#子进程要执行的代码

defrun_proc(name):

print('Runchildprocess%s(%s)...'%(name,os.getpid()))

if__name__=='__main__':

print('Parentprocess%s.'%os.getpid())

p=Process(target=run_proc,args=('test',))

print('Childprocesswillstart.')

p.start()

p.join()

print('Childprocessend.')

执行结果如下:

Parentprocess928.

Processwillstart.

Runchildprocesstest(929)...

Processend.

创建子进程时,只需要传入一个执行函数和函数的参数,创建一个Process实例,用start()方法启动,这样创建进程比fork()还要简单。

join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步。

线程

Python的标准库提供了两个模块:_thread和threading,_thread是低级模块,threading是高级模块,对_thread进行了封装。绝大多数情况下,我们只需要使用threading这个高级模块。

启动一个线程就是把一个函数传入并创建Thread实例,然后调用start()开始执行:

importtime,threading

#新线程执行的代码:

defloop():

print('thread%sisrunning...'%threading.current_thread().name)

n=0

whilen<5:

n=n+1

print('thread%s>>>%s'%(threading.current_thread().name,n))

time.sleep(1)

print('thread%sended.'%threading.current_thread().name)

print('thread%sisrunning...'%threading.current_thread().name)

t=threading.Thread(target=loop,name='LoopThread')

t.start()

t.join()

print('thread%sended.'%threading.current_thread().name)

执行结果如下:

threadMainThreadisrunning...

threadLoopThreadisrunning...

threadLoopThread>>>1

threadLoopThread>>>2

threadLoopThread>>>3

threadLoopThread>>>4

threadLoopThread>>>5

threadLoopThreadended.

threadMainThreadended.

Lock

多线程和多进程最大的不同在于,多进程中,同一个变量,各自有一份拷贝存在于每个进程中,互不影响,而多线程中,所有变量都由所有线程共享,所以,任何一个变量都可以被任何一个线程修改,因此,线程之间共享数据最大的危险在于多个线程同时改一个变量,把内容给改乱了。

balance=0

lock=threading.Lock()

defrun_thread(n):

foriinrange(100000):

#先要获取锁:

lock.acquire()

try:

#放心地改吧:

change_it(n)

finally:

#改完了一定要释放锁:

lock.release()

当多个线程同时执行lock.acquire()时,只有一个线程能成功地获取锁,然后继续执行代码,其他线程就继续等待直到获得锁为止。

获得锁的线程用完后一定要释放锁,否则那些苦苦等待锁的线程将永远等待下去,成为死线程。所以我们用try...finally来确保锁一定会被释放。

ThreadLocal

importthreading

#创建全局ThreadLocal对象:

local_school=threading.local()

defprocess_student():

#获取当前线程关联的student:

std=local_school.student

print('Hello,%s(in%s)'%(std,threading.current_thread().name))

defprocess_thread(name):

#绑定ThreadLocal的student:

local_school.student=name

process_student()

t1=threading.Thread(target=process_thread,args=('Alice',),name='Thread-A')

t2=threading.Thread(target=process_thread,args=('Bob',),name='Thread-B')

t1.start()

t2.start()

t1.join()

t2.join()

执行结果:

Hello,Alice(inThread-A)

Hello,Bob(inThread-B)

全局变量local_school就是一个ThreadLocal对象,每个Thread对它都可以读写student属性,但互不影响。你可以把local_school看成全局变量,但每个属性如local_school.student都是线程的局部变量,可以任意读写而互不干扰,也不用管理锁的问题,ThreadLocal内部会处理。

可以理解为全局变量local_school是一个dict,不但可以用local_school.student,还可以绑定其他变量,如local_school.teacher等等。

ThreadLocal最常用的地方就是为每个线程绑定一个数据库连接,HTTP请求,用户身份信息等,这样一个线程的所有调用到的处理函数都可以非常方便地访问这些资源。

以上内容为大家介绍了Python学习之进程和线程,希望对大家有所帮助,如果想要了解更多Python相关知识,请关注IT培训机构:千锋教育。https://www.mobiletrain.org/

声明:本站部分稿件版权来源于网络,如有侵犯版权,请及时联系我们。

相关推荐

  • Python字符串连接 字符串是Python中常用的数据类型,在开发过程中可以对字符创进行截取并与其他字符创进行连接。下面小编整理了5种方法完成Python字符创的连接!加号如果有其他编程语言开发经验的人,肯定知道很多语言里
  • 如何把awk脚本移植到Python 将一个awk脚本移植到Python主要在于代码风格而不是转译。脚本是解决问题的有效方法,而awk是编写脚本的出色语言。它特别擅长于简单的文本处理,它可以带你完成配置文件的某些复杂重写或目录中文件名的重
  • 使用Python删除排序数组中的重复项 问题描述:给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。不要使用额外的数组空间,你必须在原地修改输入数组并在使用O(1)额外空间的条件下完成。示例示
  • 如何迈出Python学习第一步 出于怀旧的缘故,我想分享我两年前的第一个Python程序。我最初学习Python,只是作为一名航空航天工程专业的学生想要逃避学习Spreadsheets(电子表格制作软件),而我也不知道怎么就选择了P
  • 了解Python语言中的时间处理 Python语言对于时间的处理继承了C语言的传统,时间值是以秒为单位的浮点数,记录的是从1970年1月1日零点到现在的秒数,这个秒数可以转换成我们日常可阅读形式的日期和时间:我们下面首先来看一下pyt
  • Web开发人员推荐的Python框架 您可以在没有框架的情况下创建出色的应用程序。如果您正在寻找一个Python框架,那么请查看以下5个好的选项列表!任何一个有价值的技术人员都会同意,通过允许更快的自定义和更专注于逻辑,框架可以让他们的生