python中的进程与线程

本文详细介绍了进程与线程的概念及区别,包括进程的创建、进程间通信、线程的创建、线程间通信等内容,并提供了Python代码示例。

1、基本概念

1.1 进程概念
进程是指一个程序在给定数据集合上的一次执行过程,简单理解为操作系统中正在执行的程序。

  • 每个进程都有自己独立的地址空间、内存、数据栈
  • 操作系统自动管理进程,分配执行时间
  • 进程可以派生子进程
  • 进程之间可以相互通信

1.2线程概念
线程是进程的实体,是CPU调度和分配的基本单元,线程必须依托进程存活,线程无法给予公平执行时间,会被其他线程抢占

1.3二者关系

  • 线程必须在进程中执行
  • 一个进程可以包含多个线程,有且只有一个主线程
  • 多线程共享同个地址空间、打开的文件以及其他资源
  • 多进程共享物理内存、磁盘等其他资源

2、进程

2.1创建进程
创建进程可以通过os.fork(Linux操作系统),multiprocessing,pool进程池

from multiprocessing import Pool

def text(msg):
    for i in range(3):
        print("(" + str(msg) + "):" + str(i))

if __name__ == "__main__":
    # 创建一个线程池,最大进程数为3
    pool = Pool(3)
    for i in range(10):
        # 向进程池中添加任务
        pool.apply_async(text, (i, ))

    print("---start---")
    # 关闭进程池,表示不能在往进程池中添加进程
    pool.close()
    # 等待进程池中的所有进程执行结束
    pool.join()
    print("--- end ---")

2.2进程间通信
multiprocessing提供的Queue模块可以完成进程间通信

from multiprocessing import Process,Queue
import time
#创建子进程,向队列写入数据
def write_task(q):
    if not q.full():
        for i in range(5):
            message="消息"+str(i)
            q.put(message)
            print('写入{}'.format(message))
#从队列读取数据
def read_task(q):
    time.sleep(1)
    while not q.empty():
        print("读取%s"%q.get(True,2))


if __name__=='__main__':
    print('-----父进程开始------')
    q=Queue()   #实例化一个队列
    pw=Process(target=write_task,args=(q,)) #队列作为参数传递给函数
    pr=Process(target=read_task,args=(q,))
    pw.start()
    pr.start()
    pw.join()
    pr.join()
    print("父进程结束")

3、线程

3.1创建线程
python3采用threading来创建线程
3.2线程间通信
线程之间共享数据资源,不需要通过其他方式进行通信
3.3互斥锁
线程可以对共享资源进行随意修改,会导致线程间数据调用混乱,简单的方法就是加锁,先到的线程上锁,后到的排队,等锁打开再进行
互斥锁(mutex)防止多线程同时读写某一内存区域,互斥锁引入一个状态:锁定和非锁定,互斥锁保证每一次只有一个线程进程读写操作

from threading import Thread,Lock
import time
n=100
def task():
    global n
    mutex.acquire() #上锁
    temp=n   #赋值给临时变量
    time.sleep(0.1)
    n=temp-1  #数量减1
    print("购买成功,剩余%d张电影票"%n)
    mutex.release()  #释放锁
if __name__=='__main__':
    mutex=Lock()  #实例化Lock类
    t_l=[]  #初始化一个列表
    for i in range(10):
        t=Thread(target=task) #实例化线程类
        t_l.append(t)  #将线程实例存入列表中
        t.start() #创建线程
    for t in t_l:
        t.join() #等待子线程结束

3.4消息队列在线程间通信
使用queue模块的Queue,在线程间通信,通常用于生产者和消费者模式。生产数据的模块成为生产者,处理数据的模块成为消费者,生产者与消费者之间的缓冲区称为仓库。

from queue import Queue
import threading,time,random
class Producer(threading.Thread):
    def __init__(self,name,queue):
        threading.Thread.__init__(self,name=name)
        self.data=queue
    def run(self) :
        for i in range(5):
            print("生产者%s将产品%d加入队列!"%(self.getName(),i))
            self.data.put(i)
            time.sleep(random.random())
        print("生产者%s完成!"%self.getName())
class Consumer(threading.Thread):
    def __init__(self,name,queue):
        threading.Thread.__init__(self, name=name)
        self.data = queue

    def run(self):
        for i in range(5):
            val=self.data.get()
            print("消费者%s将产品%d取出队列!" % (self.getName(), val))
            time.sleep(random.random())
        print("消费者%s完成!" % self.getName())

if __name__=='__main__':
    print("主线程开始")
    queue=Queue()
    producer=Producer('producer',queue)
    consumer=Consumer('consumer',queue)
    producer.start()
    consumer.start()
    producer.join()
    consumer.join()
    print("主线程结束")

3.5GIL
全局解释器锁(global interpreter lock),某个线程想要执行,必须先拿到 GIL,我们可以把 GIL 看作是“通行证”,并且在一个 Python 进程中,GIL 只有一个。拿不到通行证的线程,就不允许进入 CPU 执行。Python 中,无论是单核还是多核,同时只能由一个线程在执行。其根源是 GIL 的存在。
每次释放 GIL锁,线程进行锁竞争、切换线程,会消耗资源。这就导致打印线程执行时长,会发现耗时更长的原因。

并且由于 GIL 锁存在,Python 里一个进程永远只能同时执行一个线程(拿到 GIL 的线程才能执行),这就是为什么在多核CPU上,Python 的多线程效率并不高的根本原因

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

测试运维小猴子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值