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 的多线程效率并不高的根本原因

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

测试运维小猴子

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

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

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

打赏作者

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

抵扣说明:

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

余额充值