本节内容

  一、进程与线程的概念

    1.1进程

    1.2线程

    1.3进程与线程的区别

  二、线程

    2、1启一个线程

    2.2线程的2种调用方式

    2.3 join

    2.4 守护线程Daemon

    2.5线程锁

    2.6全局解析锁

    2.7递归锁

    2.8Semaphore(信号量)

    2.9事件Events(红绿灯举例)

    2.10queue队列

    2.11生产消费者模型

  三、进程

    3.1多进程

    3.2进程间通讯

    3.3进程池

 

 

1.1进程

什么是进程(process)?

  以QQ为例, QQ 要以一个整体的形式暴露给操作系统管理,里面包含对各种资源的调用,内存的管理,网络接口的调用等。。。。对各种资源管理的集合 就可以称为: 进程

  程序的执行实例称为进程。每个进程都提供执行程序所需的资源。 进程具有虚拟地址空间,可执行代码,系统对象的打开句柄,安全上下文,唯一进程标识符,环境变量,优先级类,最小和最大工作集大小以及至少一个执行线程。 每个进程都使用单个线程启动,通常称为主线程,但可以从其任何线程创建其他线程。
  程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本;进程是程序的一次执行活动,属于动态概念。在多道编程中,我们允许多个程序同时加载到内存中,在操作系统的调度下,可以实现并发地执行。这是这样的设计,大大提高了CPU的利用率。进程的出现让每个用户感觉到自己独享CPU,因此,进程就是为了在CPU上实现多道编程而提出的。

有了进程为什么还要线程?

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

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

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

例如,我们在使用qq聊天, qq做为一个独立进程如果同一时间只能干一件事,那他如何实现在同一时刻 即能监听键盘输入、又能监听其它人给你发的消息、同时还能把别人发的消息显示在屏幕上呢?你会说,操作系统不是有分时么?但我的亲,分时是指在不同进程间的分时呀, 即操作系统处理一会你的qq任务,又切换到word文档任务上了,每个cpu时间片分给你的qq程序时,你的qq还是只能同时干一件事呀。

再直白一点, 一个操作系统就像是一个工厂,工厂里面有很多个生产车间,不同的车间生产不同的产品,每个车间就相当于一个进程,且你的工厂又穷,供电不足,同一时间只能给一个车间供电,为了能让所有车间都能同时生产,你的工厂的电工只能给不同的车间分时供电,但是轮到你的qq车间时,发现只有一个干活的工人,结果生产效率极低,为了解决这个问题,应该怎么办呢?。。。。没错,你肯定想到了,就是多加几个工人,让几个人工人并行工作,这每个工人,就是线程!

 1.2线程

线程: 是操作系统最小的调度单位, 是一串指令的集合。是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。官网链接:https://docs.python.org/3/library/threading.html?highlight=threading#

线程是执行上下文,它是CPU执行指令流所需的所有信息。
假设你正在读一本书,而你现在想休息一下,但是你希望能够从你停下来的确切位置回来并继续阅读。实现这一目标的一种方法是记下页码,行号和字号。因此,阅读书籍的执行环境就是这三个数字。如果你有一个室友,并且她使用相同的技术,她可以在你不使用时拿走这本书,并从她停下的地方继续阅读。然后你可以把它拿回来,并从你原来的地方恢复。
线程以相同的方式工作。 CPU正在给你一种错觉,即它同时进行多次计算。它通过在每次计算上花费一点时间来做到这一点。它可以这样做,因为它具有每个计算的执行上下文。就像您可以与朋友共享一本书一样,许多任务可以共享CPU。在更技术层面上,执行上下文(因此是一个线程)由CPU寄存器的值组成。最后:线程与进程不同。线程是执行的上下文,而进程是与计算相关联的一堆资源。一个进程可以有一个或多个线程。澄清:与进程相关联的资源包括内存页面(进程中的所有线程具有相同的内存视图),文件描述符(例如,打开套接字)和安全凭证(例如,启动该进程的用户的ID)处理)。

 1.3进程与线程的区别:

进程 要操作cpu , 必须要先创建一个线程 ,所有在同一个进程里的线程是共享同一块内存空间的。

1、线程共享创建它的进程的地址空间; 进程有自己的地址空间。(线程共享内存空间,进程的内存是独立的)
2、线程可以直接访问其进程的数据段; 进程拥有自己父进程数据段的副本。
3、线程可以直接与其进程的其他线程通信; 进程必须使用进程间通信来与兄弟进程通信。(同一个进程的线程之间可以直接交流,两个进程想通信,必须通过一个中间代理来实现)
4、创建新线程很简单, 创建新进程需要对其父进程进行一次克隆。
5、一个线程可以控制和操作同一进程里的其他线程,但是进程只能操作子进程。
6、对主线程的更改(取消,优先级更改等)可能会影响进程的其他线程的行为; 对父进程的更改不会影响子进程。

 

二、线程

2.1启动一个线程

举例子,演示一个最简单的多线程

 1 import threading
 2 import time
 3 
 4 def run(n):
 5     print("task",n)
 6     time.sleep(2)
 7     
 8 t1 = threading.Thread(target=run,args=("t1",))
 9 t2 = threading.Thread(target=run,args=("t2",))
10 #总共运行了2秒,因为是并行的2秒
11 t1.start()
12 t2.start()
13 
14 #比较,这里会运行4秒,是先后各两秒
15 # run(t1)
16 # run(t2)

 

 2、2线程的2种调用方式

Python threading模块线程有2种调用方式,如下:

 1 import threading
 2 import time
 3 
 4 
 5 def sayhi(num):  # 定义每个线程要运行的函数
 6 
 7     print("running on number:%s" % num)
 8 
 9     time.sleep(3)
10 
11 
12 if __name__ == '__main__':
13     t1 = threading.Thread(target=sayhi, args=(1,))  # 生成一个线程实例
14     t2 = threading.Thread(target=sayhi, args=(2,))  # 生成另一个线程实例
15 
16     t1.start()  # 启动线程
17     t2.start()  # 启动另一个线程
18 
19     print(t1.getName())  # 获取线程名
20     print(t2.getName())
直接调用

相关文章: