Python多线程编程

forking工作原理

什么是forking
  • fork(分岔)在Linux系统中使用非常广泛
  • 当某一命令执行时,父进程(当前进程)fork出一个子进程
  • 父进程将自身资源拷贝一份,命令在子进程中运行时,就具有和父进程完全一样的运行环境
import os
print('Starting')
os.fork()   #生成子进程
#后续代码在父子进程中都要执行
print('Hello World')
进程的生命周期
  • 父进程fork出子进程并挂起
  • 子进程运行完毕后,释放大部分资源并通知父进程,这个时候,子进程被称作僵尸进程
  • 父进程获知子进程结束,子进程所有资源释放
import os
print('Starting')
retval = os.fork()
if retval: #父进程的retval是非0值
    print('in parent')
else:
    print('in child')

print('hello from both')
僵尸进程
  • 僵尸进程没有任何可执行代码,也不能被调度
  • 如果系统中存在过多的僵尸进程,将因为没有可用的进程号而导致系统不能产生新的进程
  • 对于系统管理员来说,可以试图杀死其父进程或重启系统来消除僵尸进程
forking编程
forking编程基本思路
  • 需要使用os模块
  • os.fork()函数实现forking功能
  • python中,绝大多数的函数只返回一次,os.fork将返回两次
  • 对fork()的调用,针对父进程返回子进程的PID;对于子进程,返回PID0
解决zombie问题
  • 父进程通过os.wait()来得到子进程是否终止的信息
  • 在子进程终止和父进程调用wait()之间的这段时间,子进程被称为zombie(僵尸)进程
  • 如果子进程还没有终止,父进程先退出了,那么子进程会持续工作。系统自动将子进程的父进程设置为init进程,init将来负责清理僵尸进程
python可以使用waitpid()来处理子进程
  • 如果程序只是短时间的运行,不用操心僵尸进程
  • 如果父进程尚未结束,子进程已经没有可执行代码了,子进程将会变成僵尸进程
  • 父进程通过waitpid()函数进行检测子进程。如果子进程已经变成僵尸进程,则处理它。
  • waitpid(m, n)的接受的参数,m取值为-1,表示与wait()有相同的功能;n的值为0表示挂起父进程(父进程暂停执行),1表示不挂起。
  • waitpid()返回值是元组(a, b),b表示状态;如果子进程是僵尸进程,b为非零值(子进程的pid),否则是0。
import os,time

print('starting...')
retval = os.fork()
if retval:
    print('父进程')
    time.sleep(10)
    print('go on')
    print(os.waitpid(-1,0))  #挂起父进程
    time.sleep(5)
else:
    print('子进程')
    time.sleep(15)
    print('子进程结束')
    exit()
print('done')

多线程编程

多线程工作原理
多线程的动机
  • 在多线程(MT)编程出现之前,电脑程序的运行由一个执行序列组成,执行序列按顺序在主机的中央处理器(CPU)中运行
  • 无论是任务本身要求顺序执行还是整个程序是由多个子任务组成,程序都是按这种方式执行的
  • 即使子任务相互独立,互相无关(即,一个子任务的结果不影响其它子任务的结果)时也是这样
  • 如果并行运行这些相互独立的子任务可以大幅度地提升整个任务的效率
多线程任务的工作特点
  • 它们本质上就是异步的,需要有多个并发事务
  • 各个事务的运行顺序可以是不确定的,随机的,不可预测的
  • 这样的编程任务可以被分成多个执行流,每个流都有一个要完成的目标
  • 根据应用的不同,这些子任务可能都要计算出一个中间结果,用于合并得到最后的结果
什么是进程
  • 计算机程序只不过是磁盘中可执行的、二进制(或其它类型)的数据
  • 进程(有时被称为重量级进程)是程序的一次执行
  • 每个进程都有自己的地址空间、内存以及其它记录其运行轨迹的辅助数据
  • 操作系统管理在其上运行的所有进程,并为这些进程公平地分配时间
什么是线程
  • 线程(有时被称为轻量级进程)跟进程有些相似。不同的是,所有的线程运行在同一个进程中,共享相同的运行环境
  • 一个进程中的各个线程之间共享同一片数据空间,所以线程之间可以比进程之间更方便地共享数据以及相互通讯
多线程编程
多线程相关模块
  • thread和threading模块允许程序员创建和管理线程
  • thread模块提供了基本的线程和锁的支持,而threading提供了更高级别、功能更强的线程管理功能
  • 推荐使用更高级别的threading模块

传递函数给Thread类
• 多线程编程有多种方法,传递函数给threading模块的Thread类是介绍的第一种方法
• Thread对象使用start()方法开始线程的执行,使用join()方法挂起程序,直到线程结束

传递可调用类给Thread类
• 传递可调用类给Thread类是介绍的第二种方法
• 相对于一个或几个函数来说,由于类对象里可以使用类的强大的功能,可以保存更多的信息,这种方法更为灵活

import subprocess
import os,threading

class Ping:
    def __init__(self,host):
        self.host = host
    def __call__(self, *args, **kwargs):
        result = subprocess.run(
            'ping -c2 %s &> /dev/null' % self.host,
            shell=True
        )
        if result.returncode == 0:
            print('%s:up' % self.host)
        else:
            print('%s:down' % self.host)

if __name__ == '__main__':
    ips = ('176.233.5.%s' % i for i in range(1, 255))
    for ip in ips:
        t = threading.Thread(target=Ping(ip))
        t.start()  #相当于执行target(*args)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值