队列
    队列 : 先进先出、数据进程安全
    队列实现方式: 管道 + 锁
    生产者消费者模型 : 解决数据供需不平衡
管道
    双向通信 数据进程不安全
    EOFError:
        管道是由操作系统进行引用计数的,
        必须在所有进程中关闭管道后才能生成EOFError异常
数据共享(不常用)
    Manager
    list dict 数据进程不安全的
进程池
    存放进程的容器
    在进程创建之初,创建固定个数的进程
    会被多个任务循环利用
    节省了进程创建和销毁的时间开销
    降低了操作系统调度进程的压力
信号量和进程池的区别
    信号量 n个任务开启n个进程,
          但同一时间只能有固定个数的进程在执行
          进程在等待被执行
    进程池 n个任务开启固定个数的进程
          因此同一时间只能有固定个数的进程在执行
          任务在等待被执行 

队列是内置锁的,所以别的应用调用它,是安全的。
凡是涉及到手动加锁的,都是不安全的。常用的一般都是消息中间件

 

没有返回值的情况

close和join成对使用

import time
from multiprocessing import Pool

def wahaha(i):
    time.sleep(1)
    print('*'*i)

if __name__ == '__main__':
    p = Pool(5) #建议的数量是CPU核数+1
    for i in range(5):
        p.apply_async(func=wahaha,args=(i,))
    p.close()  # 不能再提交新的任务
    p.join()  # 等待池中的任务都执行完

执行输出:

*
**
***
****

 

有返回值的情况

import time
from multiprocessing import Pool

def wahaha(i):
    time.sleep(1)
    return '*'*i

if __name__ == '__main__':
    p = Pool(5) #建议的数量是CPU核数+1
    res_1 = []
    for i in range(5):
        res = p.apply_async(func=wahaha,args=(i,))
        res_1.append(res)
    for i in res_1:print(i.get())

执行输出:

*
**
***
****

 

总结:

主进程默认等待子进程结束 —— 守护进程
普通的进程 : 根据你调用的函数执行结束它就结束了
进程池里的进程
  没有返回值:
    在提交任务之后:
    p.close() 不能再提交新的任务
    p.join() 等待池中的任务都执行完
  有返回值的时候:
    在提交任务之后:
    for i in res_l:print(i.get())

 

第二种写法:使用map

它不能获取返回值,参数必须是一个可迭代对象

import time
from multiprocessing import Pool

def wahaha(i):
    time.sleep(1)
    print('*'*i)

if __name__ == '__main__':
    p = Pool(5) #建议的数量是CPU核数+1
    p.map(func=wahaha,iterable=range(5))  # iterable接收一个可迭代对象

执行输出:

**
*
***
****

如果不需要返回值得,使用map即可

 

回调函数
  回调函数在什么时候执行
    子进程的任务执行完毕之后立即触发
  回调函数的参数
    子进程的返回值
  回调函数是由谁执行的
    主进程执行的
  在哪儿用?
    爬虫 :
      如果要爬取多个格式相同的网页
      真正影响程序效率的是网络的延迟
      计算 分析 处理网页的时间是很快的

 

如果主进程要处理很久,那么就不适合用回调函数

当你不确定,到底有没有回调函数快?测试一下就知道了。
先不用回调函数,打印执行时间
再用回调函数,打印执行时间,对比一下,就知道了。

 

操作系统线程理论

线程概念的引入背景

进程

  之前我们已经了解了操作系统中进程的概念,程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本;进程是程序的一次执行活动,属于动态概念。在多道编程中,我们允许多个程序同时加载到内存中,在操作系统的调度下,可以实现并发地执行。这是这样的设计,大大提高了CPU的利用率。进程的出现让每个用户感觉到自己独享CPU,因此,进程就是为了在CPU上实现多道编程而提出的。

有了进程为什么要有线程

  进程有很多优点,它提供了多道编程,让我们感觉我们每个人都拥有自己的CPU和其他资源,可以提高计算机的利用率。很多人就不理解了,既然进程这么优秀,为什么还要线程呢?其实,仔细观察就会发现进程还是有很多缺陷的,主要体现在两点上:

  • 进程只能在一个时间干一件事,如果想同时干两件事或多件事,进程就无能为力了。

  • 进程在执行的过程中如果阻塞,例如等待输入,整个进程就会挂起,即使进程中有些工作不依赖于输入的数据,也将无法执行。

  如果这两个缺点理解比较困难的话,举个现实的例子也许你就清楚了:如果把我们上课的过程看成一个进程的话,那么我们要做的是耳朵听老师讲课,手上还要记笔记,脑子还要思考问题,这样才能高效的完成听课的任务。而如果只提供进程这个机制的话,上面这三件事将不能同时执行,同一时间只能做一件事,听的时候就不能记笔记,也不能用脑子思考,这是其一;如果老师在黑板上写演算过程,我们开始记笔记,而老师突然有一步推不下去了,阻塞住了,他在那边思考着,而我们呢,也不能干其他事,即使你想趁此时思考一下刚才没听懂的一个问题都不行,这是其二。

  现在你应该明白了进程的缺陷了,而解决的办法很简单,我们完全可以让听、写、思三个独立的过程,并行起来,这样很明显可以提高听课的效率。而实际的操作系统中,也同样引入了这种类似的机制——线程。

线程的出现

  60年代,在OS中能拥有资源和独立运行的基本单位是进程,然而随着计算机技术的发展,进程出现了很多弊端,一是由于进程是资源拥有者,创建、撤消与切换存在较大的时空开销,因此需要引入轻型进程;二是由于对称多处理机(SMP)出现,可以满足多个运行单位,而多个进程并行开销过大。
  因此在80年代,出现了能独立运行的基本单位——线程(Threads)
  注意:进程是资源分配的最小单位,线程是CPU调度的最小单位.
     每一个进程中至少有一个线程。 

 

操作系统是管理进程的,每个进程是资源隔离的。在一个操作系统中,同一时间,可以有多个任务。

多个任务之间的内存必须隔离开。比如使用qq的时候还能使用微信。并发要求日益增加,比如聊天的时候,可以开多个窗口,还可以看电影,听歌...

开启一个子进程的开销,是很大的。操作系统在进程之间的切换,时间开销也很大。

进程之间的通信:

数据共享 : 时间开销
如果多个子进程之间的数据共享量过多的时候,
就不应该将这些数据隔离开

一个进程 —— 实现不了并发
你既不希望数据隔离,还要实现并发的效果。那么就应该使用线程

线程是轻量级的进程
线程的创建和销毁所需要的时间开销都非常小
线程直接使用进程的内存
线程不能独立存在,要依赖于进程

 

进程和线程的关系

  python 全栈开发,Day41(线程概念,线程的特点,进程和线程的关系,线程和python 理论知识,线程的创建)

  线程与进程的区别可以归纳为以下4点:
  1)地址空间和其它资源(如打开文件):进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。
  2)通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。
  3)调度和切换:线程上下文切换比进程上下文切换要快得多。
  4)在多线程操作系统中,进程不是一个可执行的实体。
 
 
print(123)

执行输出:123

真正执行代码的是线程
程序启动是一个进程。

使用线程执行代码,接受CPU调度。
线程的时间开销小于进程时间开销

 

线程的特点

  在多线程的操作系统中,通常是在一个进程中包括多个线程,每个线程都是作为利用CPU的基本单位,是花费最小开销的实体。线程具有以下属性。
  1)轻型实体
  线程中的实体基本上不拥有系统资源,只是有一点必不可少的、能保证独立运行的资源。
  线程的实体包括程序、数据和TCB。线程是动态概念,它的动态特性由线程控制块TCB(Thread Control Block)描述。
TCB包括以下信息:
(1)线程状态。
(2)当线程不运行时,被保存的现场资源。
(3)一组执行堆栈。
(4)存放每个线程的局部变量主存区。
(5)访问同一个进程中的主存和其它资源。
用于指示被执行指令序列的程序计数器、保留局部变量、少数状态参数和返回地址等的一组寄存器和堆栈。
TCB包括以下信息

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-05-16
  • 2022-12-23
  • 2022-01-10
  • 2021-08-12
  • 2022-12-23
  • 2021-05-25
猜你喜欢
  • 2021-12-02
  • 2021-12-16
  • 2021-11-18
  • 2022-12-23
  • 2021-04-02
  • 2021-06-23
  • 2021-07-14
相关资源
相似解决方案