Python的进程、线程、协程、threading模块、multiprocessing模块

目录

1、进程与线程

1.1  定义

1.1.1 进程

1.1.2 线程

1.2 线程与进程的关系

1.3  进程状态模型

 1.4 多进程与多线程的比较

2、threading模块

1.1  功能

1.2  threading——Thread

1.2.1 Thread构造方法

1.2.2  Thread实例方法

1.3  threading——Lock

1.3.1  Lock()/RLock:普通锁(互斥锁)

1.3.2  Semaphore :信号(信号锁)

1.3.3  Event: 事件锁

1.3.4  Condition: 条件

1.3.5  死锁

1.3  threading——GIL(全局解释器锁)

3、进程与多进程

3.1  进程

3.2  进程与多进程-os.fork

3.2.1  创建子进程

3.2.2  孤儿进程

3.2.3  僵尸进程

3.3  进程与多进程-multiprocessing

3.3.1  Multiprocessing

3.3.2  Process 类

3.3.3  multiprocessing—进程间数据共享

3.3.4  multiprocessing—进程锁

3.3.5  进程与多进程-multiprocessing.Pool

3.3.6  Python中多进程与多线程

3.3.7  多进程与多线程的生产者消费者模式

4、协程

4.1 概念

 4.2  协程与线程比较

4.2.1  协程的缺点

4.3  python对协程的支持

4.3.1  协程—yield

4.3.2  asyncio协程

4.3.3  协程锁、协程队列

5、系统知识


1、进程与线程

1.1  定义

1.1.1 进程

        进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,正在运行的程序,是系统进行资源分配和调度的基本单。

1.1.2 线程

          线程是操作系统最小的调度单位, 是一串指令的集合。线程被称为轻量级进程(Lightweight Process,LWP),是cpu调度的基本单位,组成:线程ID、当前指令指针(PC)、寄存器集合、堆栈组成 ,在单个程序中同时运行多个线程完成不同的工作,称为多线程。

1.2 线程与进程的关系

        真正在cpu上运行的是线程 ,线程共享内存空间;进程的内存是独立的 ,一个线程只能属于一个进程,而一个进程可以有多个线程, 但至少有一个线程。

        资源分配给进程,同一进程的所有线程共享进程的所有资源。进程的资源是独立的,同一个进程的线程之间可以直接交流;两个进程想通信,必须通过一个中间代理来实。

        创建新的线程很简单,创建一个新的进程都需要对其父进程进行一次克隆,一个线程可以控制和操作同一个进程里的其他线程,进程只能操作子进程,一个主线程改变,可能会影响其他线程,改变父进程不会影响子进程。

1.3  进程状态模型

 1.4 多进程与多线程的比较

2、threading模块

1.1  功能

      threading用于提供线程相关的操作,线程是应用程序中工作的最小单元。

      threading模块提供的常用类:

                Thread:创建线程

                Lock/RLock:互斥锁

1.2  threading——Thread

1.2.1 Thread构造方法

        构造方法:

        Thread(group=None, target=None, name=None, args=(), kwargs={})

  •         group: 线程组,目前还没有实现,库引用中提示必须是None;
  •         target: 要执行的方法;
  •         name: 线程名;
  •          args/kwargs: 要传入方法的参数

1.2.2  Thread实例方法

  •         t.name获取或设置线程的名称
  •         t.getName()/setName(name): 获取/设置线程名。
  •         t.is_alive()、t.isAlive()判断线程是否为激活状态,返回线程是否在运行,正在运行指启动后、终止前。
  •         t.ident 获取线程的标识符。线程标识符是一个非零整数,只有在调用了start()方法之后该属性才有效,否则它只返回None。
  •         t.run() 线程被cpu调度后自动执行线程对象的run方法。         
  •         t.start(): 线程准备就绪,等待CPU调度,start会自动调用t.run()。
  •         t.join([timeout]): 阻塞当前上下文环境的线程,直到调用此方法的线程终止或到达指定的timeout (可选参数)。
  •         t.setDaemon(bool): 设置是后台线程(默认前台线程(False)),(在start之前设置) 如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,主线程和后台线程均停止。如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止
  •         t.isDaemon:判断是否为后台线程。
import requests
import time
from threading import Thread

def cost(f):
    # print("this is cost")
    def _cost(*args, **kwargs):
        start = time.time()
        result = f(*args, **kwargs)
        end = time.time()
        print(f"执行{f.__name__}花费{end-start}s")
        return result
    return _cost

def get_content(url):
    print("start......")
    text = requests.get(url).text
    time.sleep(0.5)
    print("get content")

@cost
def main():
    t_list = []
    for i in range(5):
        # get_content("https://www.baidu.com")
        #创建线程
        #target  --》 执行要传入的方法名字, 要做什么
        #args    --》 指定方法需要传入的参数  元组类型
        t = Thread(target=get_content,args=("https://www.baidu.com",))
        t_list.append(t)
        #设置为后台线程, 主线程退出,子线程也退出
        #t.setDaemon(True)
        #启动线程
        t.start()  #自动调用t.run()
        # t.join()
    #阻塞当前环境上下文,直到为t的线程执行完成
    # [ t.join() for t in t_list]
    print("end.........")
main()


输出:
start......
start......
start......
end.........
执行main花费0.0s
get contentget content

get content
get content
get content

 使用自定义线程:

import  threading

class MyThread(threading.Thread):
    def __init__(self,num):
         super().__init__()
        self.num = num
     def run(self):
         print(f"running in numbers:{self.num}")

t1 = MyThread(1)
t2 = MyThread(2)
t1.start()
t2.start()

1.3  threading——Lock

        资源总是有限的,程序运行如果对同一个对象进行操作,则有可能造成 一些异常情况,如: 数据前后读取不一致,资源的争用甚至导致死锁。

        在多线程中使用lock可以让多个线程在共享资源的时候遵循一定的规则。

        常见锁类型 :

  •         Lock()/RLock:普通锁(互斥锁) 解决资源争用,数据读取不一致等
  •         Semaphore :信号量最多允许同时N个线程执行内容
  •         Event: 事件锁 根据状态位,决定是否通过事件
  •         Condition: 条件

1.3.1  Lock()/RLock:普通锁(互斥锁)

        解决资源争用,数据读取不一致等

        构造方法: Lock()

        实例方法:

  •         acquire([timeout]): 尝试获得锁定。使线程进入同步阻塞状态。
  •         release(): 释放锁。使用前线程必须已获得锁定,否则将抛出异常。
import threading
import time

num = 0
def sum_num(i):
    print(f"lock start....{i}")
    # lock.acquire()  #获得锁
    with lock:
        global num
        time.sleep(0.5)
        num += i
        print(num)
    # lock.release()  #释放锁

lock = threading.RLock()  #互斥锁对象
for i in range(5):
    t = threading.Thread(target=sum_num, args=(i,))
    t.start()

输出:
lock start....2
lock start....3
lock start....4
0
1
3
6
10

         Lock 原始锁:获取锁之前不做判断,直到获取到锁为止。

        RLOCK 重入锁:获取锁之前先判断,如果自己有了锁,那就立即放回。

1.3.2  Semaphore :信号(信号锁)

        最多允许同时N个线程执行内容

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值