当前位置: 移动技术网 > IT编程>脚本编程>Python > 12 认识进程与线程 (进阶)

12 认识进程与线程 (进阶)

2018年11月01日  | 移动技术网IT编程  | 我要评论

送女友什么生日礼物,梁雅琳,哈尔滨江南职业技术学院

认识进程与线程(python)

  一段时间没有更新博客了,今天和大家讲讲关于 python 进程和线程的知识点。(个人心得,多多指教!)

阶段一:并发与并行的深入理解

​ 并行一定是并发,但并发不一定是并行。

​ 并行是相对的,并行是绝对的。

1、关于并行与并发的问题引入:

问题一: 计算机是如何执行程序指令的?

问题二: 计算机如何模拟出并行执行的效果?

问题三: 真正的并行需要依赖什么?

2、计算机执行指令示意图

2、轮询调度实现并发执行

并发:看上去一起执行,同时在发生

并行:真正一起执行,同时在进行

调度算法:

​ 时间片轮转

​ 优先级调度

3、并行需要的核心条件

​ 并行真正的核心条件是有多个cpu

阶段二:多进程实现并行

1、多进程并行问题引入

问题一: 什么是进程?

问题二: 如何在python中使用进程?

问题三: 多进程实现并行的必要条件是什么?

2、进程的概念

计算机程序是存储在磁盘上的可执行二进制(或其他类型)文件。

​ 只有把它们加载到内存中,并被操作系统调用它们才会拥有其自己的生命周期。

进程则是表示的一个正在执行的程序。

​ 每个进程都拥有自己的地址空间、内存、数据栈以及其他用于跟踪执行的辅助数据

操作系统负责其上所有进程的执行。

​ 操作系统会为这些进程合理地分配执行时间。

3、在python中直接执行耗时函数
import time
​
print('main-task start:', time.asctime(time.localtime(time.time())))
​
def func():
    print('sub-task start:', time.asctime(time.localtime(time.time())))
    time.sleep(5)
    print('sub-task end:', time.asctime(time.localtime(time.time())))
​
func()
time.sleep(5)
print('main-task end:', time.asctime(time.localtime(time.time())))
4、在python中使用进程来分担耗时任务
import time
import multiprocessing
​
def func(n):
    for i in range(n):
        for a in range(n):
            for b in range(n):
                print(b)
​
start_time = time.time()
​
p = multiprocessing.process(target=func, args=(50, ))    # 实例化,创建一个进程
# 参数如何传?  args=(50, )  kwargs={'n': 50}
p.start()   # 开启进程
p.join()    # 主进程等待子进程结束
​
func(50)
# func(50)
​
end_time = time.time()
print('运行了%ds!' % (end_time - start_time))
5、多进程并行的必要条件

总进程数量不多于cpu核心数量!

​ 因此,现在运行的程序都是轮询调度产生的并行假象。但是在python层面的确获得了并行!

阶段三:多线程实现并发

1、多线程并发问题引入

问题一: 什么是线程?

问题二: 如何在python中使用线程?

问题三: 为什么多线程不是并行?

2、线程的概念

线程被称作轻量级进程。

​ 与进程类似,不过它们是在同一个进程下执行的。并且它们会共享相同的上下文。

当其他线程运行时,它可以被抢占(中断)和临时挂起(也成为睡眠)— 让步

​ 线程的轮询调度机制类似于进程的轮询调度。只不过这个调度不是由操作系统来负责,而是由python解释器来负责。

3、在python中使用线程来避开阻塞任务
import time
import multiprocessing
import threading
​
print('---outer--start---:', time.asctime(time.localtime(time.time())))
​
def func():
    print('---inner--start---:', time.asctime(time.localtime(time.time())))
    time.sleep(5)
    print('---inner--end---:', time.asctime(time.localtime(time.time())))
​
"""
在进程里可以模拟耗时任务,但是在线程里只能模拟阻塞任务,不能模拟耗时任务。因为多线程只有一个核心进程。
"""
p = multiprocessing.process(target=func)    # 创建子进程
t = threading.thread(target=func)   # 创建子线程
t.start()   # 开启子线程
​
time.sleep(5)
print('---outer--end---:', time.asctime(time.localtime(time.time())))

cpu在任意一个进程里,任意时刻,只能执行一个线程

​ 对进程的轮询是操作系统负责调度

​ 对线程的轮询是python解释器负责调度

4、gil锁 全局解释器锁

python在设计的时候,还没有多核处理器的概念。

因此,为了设计方便与线程安全,直接设计了一个锁。

这个锁要求,任何进程中,一次只能有一个线程在执行。

因此,并不能为多个线程分配多个cpu。

所以python中的线程只能实现并发,

而不能实现真正的并行。

但是python3中的gil锁有一个很棒的设计,

在遇到阻塞(不是耗时)的时候,会自动切换线程。

5、gil锁带给我们的新认知

遇到阻塞就自动切换。因此我们可以利用这种机制来有效的避开阻塞~充分利用cpu

阶段四:使用多进程与多线程来实现并发服务器

关键点一: 多进程是并行执行,

​ 相当于分别独立得处理各个请求。

关键点二: 多线程,虽然不能并行运行,

​ 但是可以通过避开阻塞切换线程

​ 来实现并发的效果,并且不浪费cup

from socket import *
from multiprocessing import process     # 进程
from threading import thread    # 线程
​
# 创建套接字
server = socket()
server.bind(('', 9999))
server.listen(1000)
​
# 定义函数
def func(conn):
    while true:
        recv_data = conn.recv(1024)
        if recv_data:
            print(recv_data)
            conn.send(recv_data)
        else:
            conn.close()
            break
​
​
while true:   # 循环去监听
    conn, addr = server.accept()
    # 每生成一个对等连接套接字,我就生成一个进程、线程,并且我让这个进程、线程去服务这个连接过来的客户端
​
    # p = process(target=func, args=(conn, ))    # 生成一个进程
    # p.start()   # 启动进程
​
​
    t = thread(target=func, args=(conn, ))    # 生成一个线程
    t.start()   # 启动线程

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网