day41 Pyhton 并发编程04
内容回顾
socket
最底层的网络通信
所有的网络通信都是基于socket
进程
什么是进程?
是操作系统的发展过程中,为了提高cpu的利用率,在操作系统同时运行多个程序的时候,为了数据的安全\代码不混乱而创造的一个概念
每一个程序运行起来都至少是一个进程
进程是计算机中最小的资源分配单位
进程被操作系统调度的,有很多相关的算法--早期的操作系统
进程之间是数据隔离的
进程的三状态 就绪 运行 阻塞
同步异步
同步:一个任务的执行依赖另一个事务的结束
join lock
异步:一个任务的执行不依赖另一个事务的结束
start terminate
阻塞非租塞
阻塞 :accept recv recvfrom queue.get join
非租塞: setblocking = False
并发并行
并行是特殊的并发
并行就是 同一时刻 两个以上的程序同时在cpu上执行
并发就是 同一时段 两个以上的程序看起来在同时执行
IO概念: 文件操作 数据库操作 网络传输 用户输入输出
Input 得到bytes/str
Output 发送数据/输出数据
因为进程与进程之间本质上是异步且数据隔离
守护进程:子进程等待主进程的代码结束就结束了
同步控制
join
锁 -互斥锁: 多个进程同时对一个数据进行操作的时候,操作同一个文件/数据库/管道/Manager.dict
信号量
事件
数据共享 - 数据不安全
Manager
IPC-进程之间通信
管道
队列 - 生产者消费者模型(为了解决数据的生产和处理的效率问题)
第三方工具(消息队列,消息中间件)
进程池
解决大量任务 开启多个进程的开销过大的问题
节省资源,提高并发效率的
一般开进程数 cpu_count *1 or 2
今日内容
初识进程
为什么要有线程
线程在操作系统中有什么特点
线程在python语言中有什么特点
GIL全局解释器锁
为什么要有全局解释器锁
在python中如何开启线程
线程的基础的使用
线程的概念
# 多进程 socket server # 只要来了一个client请求 开一个进程 # 进程开多了就会卡 # 进程的调度 # 进程的开启的开销 # 给操作系统的负担 # 数据\文件\代码 # 记录当前的执行位置 # 假设有一个机制 # 开启进程的开销变短 # 调度的时间也变短 # 操作系统减负 # 线程是计算机中被CPU调度的最小单位 # 线程 : 轻量级的进程/轻型进程 # 线程本身创建出来就是为了解决并发问题的 # 并且它的整体效率比进程要高 # 但是线程实际上也有一些性能上的限制\管理调度开销 # 在整个程序界: # 如果你的程序需要数据隔离 : 多进程 # 如果你的程序对并发的要求非常高 : 多线程 # socketserver 多线程的 # web的框架 django flask tornado 多线程来接收用户并发的请求 # 线程 # 轻量级 # 在进程中数据共享 # 是进程的一部分,不能独立存在的 # 计算机中能被CPU调度的最小单位 # 进程 # 对操作系统的压力大 # 数据隔离 # 可以在操作系统中独立存在 # 计算机中资源分配的最小单位 # 在整个编程界 # 同一个进程中的多个线程能不能同时使用多个cpu # python # 单核的 一个cpu # 多核的 作为一门脚本语言 # 线程锁这件事儿是有Cpython解释器完成 # 对于python来说 同一时刻只能有一个线程被cpu访问 # 彻底的解决了多核环境下的安全问题 # 线程锁 : 全局解释器锁 GIL # 1.这个锁是锁线程的 # 2.这个锁是解释器提供的 # 多线程仍然有它的优势 # 你的程序中用到cpu真的多么 # 如果100% 90%的时间都消耗在计算上,那么cpython解释器下的多线程对你来说确实没用 # 但是你写的大部分程序 的时间实际上都消耗在了IO操作上 # 遇到高计算型 # 开进程 4个进程 每个进程里开n个线程 # 换个解释器
threading模块
import os
import time
from threading import Thread
# Process 进程类
# Thread 线程类
# 1.初识线程模块
def func():
print('start',os.getpid())
time.sleep(1)
print('end')
if __name__ == '__main__':
t = Thread(target=func)
t.start()
for i in range(5):
print('主线程',os.getpid())
time.sleep(0.3)
import time from threading import Thread def func(): n = 1 + 2 + 3 n ** 2 if __name__ == '__main__': start = time.time() lst = [] for i in range(100): t = Thread(target=func) t.start() lst.append(t) for t in lst: t.join() print(time.time() - start)#0.026000261306762695 # import time # from multiprocessing import Process as Thread # def func(): # n = 1 + 2 + 3 # n**2 # # if __name__ == '__main__': # start = time.time() # lst = [] # for i in range(100): # t = Thread(target=func) # t.start() # lst.append(t) # for t in lst: # t.join() # print(time.time() - start)#15.187999963760376
# 3.线程的数据共享 from threading import Thread n = 100 def func(): global n n -= 1 t = Thread(target=func) t.start() t.join() print(n)
# 4.开启线程的另一种方式 from threading import Thread class Mythread(Thread): def __init__(self,arg): super().__init__() self.arg = arg def run(self): print('in son',self.arg) t = Mythread(123) t.start()
# 5.threading模块中的其他功能 import time from threading import Thread,currentThread,activeCount,enumerate class Mythread(Thread): def __init__(self,arg): super().__init__() self.arg = arg def run(self): time.sleep(1) print('in son',self.arg,currentThread()) for i in range(10): t = Mythread(123) t.start() print(t.ident) print(activeCount()) print(enumerate())
守护线程
import time from threading import Thread def func(): while True: print('in func') time.sleep(0.5) def func2(): print('start func2') time.sleep(10) print('end func2') Thread(target=func2).start() t = Thread(target=func) t.setDaemon(True) t.start() print('主线程') time.sleep(2) print('主线程结束')
守护进程 只守护主进程的代码,主进程代码结束了就结束守护,守护进程在主进程之前结束
守护线程 随着主线程的结束才结束,守护线程是怎么结束的
进程 terminate 强制结束一个进程的
线程 没有强制结束的方法
线程结束 : 线程内部的代码执行完毕 那么就自动结束了
多线程实现socket_server
server import socket from threading import Thread def talk(conn): while True: msg = conn.recv(1024).decode() conn.send(msg.upper().encode()) sk = socket.socket() sk.bind(('127.0.0.1',9000)) sk.listen() while True: conn,addr = sk.accept() Thread(target=talk,args = (conn,)).start()
import socket sk = socket.socket() sk.connect(('127.0.0.1',9000)) while True: sk.send(b'hello') print(sk.recv(1024))