昨日内容回顾

  • 操作系统发展史

    1.穿孔卡片
    CPU利用率极低
    2.联机批处理系统
    CPU效率有所提升
    3.脱机批处理系统
    CPU效率极大提升(现代计算机雏形) 多道技术(单核CPU)
    串行:多个任务依次排队执行
    多道:切换+保存状态
  • 进程理论

    程序与进程的区别
    程序是死的进程是活的 进程的调度算法
    先来先服务
    短作业优先
    时间片轮转法+多级反馈队列 进程的三状态
    就绪态 运行态 阻塞态(只有经过就绪态的进程才能进入运行态) 任务的提交方式
    同步:提交完任务之后原地等待任务的结果 期间不做任何事情
    异步:提交完任务之后不愿地等待 结果由反馈机制(异步回调机制) 进程的状态
    阻塞态:阻塞态
    非阻塞:就绪态 运行态
    # 高效的程序尽量一直处于非阻塞态 异步非阻塞:效率最高的
  • 开启进程的多种方式

    # 平时多留意一些比较高端的内置模块
    .start() 异步提交 告诉操作系统开设进程
  • 进程join方法

    主进程等待子进程运行结束之后再继续执行
    # 注意多个进程在等待其中一个执行的时候另外几个也相当于在等待执行
  • 进程对象方法

    1.获取进程号(子、父)
    2.获取进程名称
    3.杀死进程
    4.判断进程是否存活
  • 进程间数据默认是隔离的

    global、nonlocal(名称空间)

今日内容概要

  • 僵尸进程与孤儿进程
  • 守护进程
  • 互斥锁(重点)
  • 消息队列
  • 实现进程间数据交互(IPC机制)
  • 生产者消费者模型
  • 线程理论(重要)

今日内容详细

僵尸进程与孤儿进程

# 僵尸进程
进程代码运行结束之后并没有直接结束而是需要等待回收子进程资源才能结束
# 孤儿进程
即主进程已经死亡(非正常)但是子进程还在运行

守护进程

守护进程:即守护着某个进程 一旦这个进程结束那么也随之结束

from multiprocessing import Process
import time def test(name):
print('总管:%s is running' % name)
time.sleep(3)
print('总管:%s is over' % name) if __name__ == '__main__':
p = Process(target=test, args=('jason',))
p.daemon = True # 设置为守护进程(一定要放在start语句上方)
p.start()
print("皇帝jason寿终正寝")
time.sleep(0.1)

互斥锁

问题:并发情况下操作同一份数据 极其容易造成数据错乱
解决措施:将并发变成串行 虽然降低了效率但是提升了数据的安全 锁就可以实现将并发变成串行的效果
行锁、表锁 使用锁的注意事项
在主进程中产生 交由子进程使用
1.一定要在需要的地方加锁 千万不要随意加
2.不要轻易的使用锁(死锁现象)
# 在以后的编程生涯中 几乎不会解除到自己操作锁的情况 import json
from multiprocessing import Process, Lock
import time
import random # 查票
def search(name):
with open(r'data.txt', 'r', encoding='utf8') as f:
data_dict = json.load(f)
ticket_num = data_dict.get('ticket_num')
print('%s查询余票:%s' % (name, ticket_num)) # 买票
def buy(name):
# 先查票
with open(r'data.txt', 'r', encoding='utf8') as f:
data_dict = json.load(f)
ticket_num = data_dict.get('ticket_num')
# 模拟一个延迟
time.sleep(random.random())
# 判断是否有票
if ticket_num > 0:
# 将余票减一
data_dict['ticket_num'] -= 1
# 重新写入数据库
with open(r'data.txt', 'w', encoding='utf8') as f:
json.dump(data_dict, f)
print('%s: 购买成功' % name)
else:
print('不好意思 没有票了!!!') def run(name,mutex):
search(name)
mutex.acquire() # 抢锁
buy(name)
mutex.release() # 释放锁 if __name__ == '__main__':
mutex = Lock()
for i in range(1, 11):
p = Process(target=run, args=('用户%s' % i,mutex))
p.start()

消息队列

参考:https://zhuanlan.zhihu.com/p/447973258

队列:先进先出

from multiprocessing import Queue

q = Queue(5)  # 括号内可以填写最大等待数

# 存放数据
q.put(111)
q.put(222)
# print(q.full()) # False 判断队列中数据是否满了
q.put(333)
q.put(444)
q.put(555)
# print(q.full())
# q.put(666) # 超出范围原地等待 直到有空缺位置
# 提取数据
print(q.get())
print(q.get())
print(q.get())
print(q.get())
print(q.get())
# print(q.get()) # 没有数据之后原地等待直到有数据为止
print(q.get_nowait()) # 没有数据立刻报错 """
full和get_nowait能否用于多进程情况下的精确使用
不能!!! 队列的使用就可以打破进程间默认无法通信的情况
"""

IPC机制(实现进程间数据交互)

from multiprocessing import Queue, Process

def producer(q):
q.put("子进程p放的数据") def consumer(q):
print('子进程c取的数据',q.get()) if __name__ == '__main__':
q = Queue()
p = Process(target=producer, args=(q,))
c = Process(target=consumer, args=(q,))
p.start()
c.start() # q.put('主进程放的数据')
# p = Process(target=consumer, args=(q,))
# p.start()
# p.join()
# print(q.get())
# print('主')

生产者消费者模型

"""
生产者
负责产生数据(做包子的)
消费者
负责处理数据(吃包子的)
该模型需要解决恭喜不平衡现象
"""
from multiprocessing import Queue, Process, JoinableQueue
import time
import random def producer(name, food, q):
for i in range(10):
print('%s 生产了 %s' % (name, food))
q.put(food)
time.sleep(random.random()) def consumer(name, q):
while True:
data = q.get()
print('%s 吃了 %s' % (name, data))
q.task_done() if __name__ == '__main__':
# q = Queue()
q = JoinableQueue()
p1 = Process(target=producer, args=('大厨jason', '玛莎拉', q))
p2 = Process(target=producer, args=('印度阿三', '飞饼', q))
p3 = Process(target=producer, args=('泰国阿人', '榴莲', q))
c1 = Process(target=consumer, args=('班长阿飞', q)) p1.start()
p2.start()
p3.start()
c1.daemon = True
c1.start() p1.join()
p2.join()
p3.join() q.join() # 等待队列中所有的数据被取干净 print('主')

线程理论

什么是线程?
进程其实是一个资源单位 真正被CPU执行的其实是进程里面的线程
"""
进程类似于是工厂 线程类似于是工厂里面的一条条流水线
所有的进程肯定含有最少一个线程
"""
进程间数据默认是隔离的 但是同一个进程内的多个线程数据是共享的

开设线程的两种方式

"""
开设进程需要做哪些操作
1.重新申请一块内存空间
2.将所需的资源全部导入
开设线程需要做哪些操作
上述两个步骤都不需要 所以开设线程消耗的资源远比开设进程的少!!!
"""
from threading import Thread
import time def test(name):
print('%s is running' % name)
time.sleep(3)
print('%s is over' % name) t = Thread(target=test, args=('jason',))
t.start()
print('主') class MyClass(Thread):
def __init__(self,name):
super().__init__()
self.name = name def run(self):
print('%s is running' % self.name)
time.sleep(3)
print('%s is over' % self.name) obj = MyClass('jason')
obj.start()
print('主线程')

线程对象的其他方法

1.join方法
2.获取进程号(验证同一个进程内可以开设多个线程)
3.active_count统计当前正在活跃的线程数
4.current_thread

守护线程

"""
主线程的结束意味着整个进程的结束
所以主线程需要等待里面所有非守护线程的结束才能结束
"""
from threading import Thread
from multiprocessing import Process
import time
def foo():
print(123)
time.sleep(3)
print("end123")
def bar():
print(456)
time.sleep(1)
print("end456")
if __name__ == '__main__':
t1=Thread(target=foo)
t2=Thread(target=bar)
t1.daemon=True
t1.start()
t2.start()
print("main-------")

线程数据共享

from threading import Thread
money = 100 def test():
global money
money = 999 t = Thread(target=test)
t.start()
t.join()
print(money)

线程互斥锁

from threading import Thread, Lock
from multiprocessing import Lock
import time num = 100 def test(mutex):
global num
mutex.acquire()
# 先获取num的数值
tmp = num
# 模拟延迟效果
time.sleep(0.1)
# 修改数值
tmp -= 1
num = tmp
mutex.release() t_list = []
mutex = Lock()
for i in range(100):
t = Thread(target=test, args=(mutex,))
t.start()
t_list.append(t)
# 确保所有的子线程全部结束
for t in t_list:
t.join()
print(num)

TCP服务端实现并发

import socket
from threading import Thread
from multiprocessing import Process server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen(5) def talk(sock):
while True:
try:
data = sock.recv(1024)
if len(data) == 0: break
print(data.decode('utf8'))
sock.send(data + b'gun dan!')
except ConnectionResetError as e:
print(e)
break
sock.close() while True:
sock, addr = server.accept()
print(addr)
# 开设多进程或者多线程
t = Thread(target=talk, args=(sock,))
t.start()

作业

1.百度搜索什么是"乐观锁与悲观锁"
2.百度搜索什么是"消息队列"
3.百度搜索什么是"二十三种设计模式"
# 平时就可以练习算法(冒泡 二分 插入 快排 堆排 桶排)
笔纸写出来的:冒泡 二分 插入 快排
能够描述出内部原理的:堆排 桶排 午间练习
将之前的TCP服务端变成多并发的效果

4、网络并发编程--僵尸进程、孤儿进程、守护进程、互斥锁、消息队列、IPC机制、生产者消费者模型、线程理论与实操的更多相关文章

  1. python并发编程-进程间通信-Queue队列使用-生产者消费者模型-线程理论-创建及对象属性方法-线程互斥锁-守护线程-02

    目录 进程补充 进程通信前言 Queue队列的基本使用 通过Queue队列实现进程间通信(IPC机制) 生产者消费者模型 以做包子买包子为例实现当包子卖完了停止消费行为 线程 什么是线程 为什么要有线 ...

  2. 并发编程(一): POSIX 使用互斥量和条件变量实现生产者/消费者问题

    boost的mutex,condition_variable非常好用.但是在Linux上,boost实际上做的是对pthread_mutex_t和pthread_cond_t的一系列的封装.因此通过对 ...

  3. [并发编程 - 多线程:信号量、死锁与递归锁、时间Event、定时器Timer、线程队列、GIL锁]

    [并发编程 - 多线程:信号量.死锁与递归锁.时间Event.定时器Timer.线程队列.GIL锁] 信号量 信号量Semaphore:管理一个内置的计数器 每当调用acquire()时内置计数器-1 ...

  4. 网络编程基础----并发编程 ---守护进程----同步锁 lock-----IPC机制----生产者消费者模型

    1  守护进程: 主进程 创建 守护进程   辅助主进程的运行 设置进程的 daemon属性 p1.daemon=True 1 守护进程会在主进程代码执行结束后就终止: 2 守护进程内无法再开启子进程 ...

  5. (并发编程)进程IPC,生产者消费者模型,守护进程补充

    一.IPC(进程间通信)机制进程之间通信必须找到一种介质,该介质必须满足1.是所有进程共享的2.必须是内存空间附加:帮我们自动处理好锁的问题 a.from multiprocessing import ...

  6. 进程同步控制(锁,信号量,事件), 进程通讯(队列和管道,生产者消费者模型) 数据共享(进程池和mutiprocess.Pool模块)

    参考博客 https://www.cnblogs.com/xiao987334176/p/9025072.html#autoid-1-1-0 进程同步(multiprocess.Lock.Semaph ...

  7. Python守护进程、进程互斥锁、进程间通信ICP(Queue队列)、生产者消费者模型

    知识点一:守护进程 守护进程:p1.daemon=True 守护进程其实就是一个“子进程“,守护=>伴随 守护进程会伴随主进程的代码运行完毕后而死掉 进程:当父进程需要将一个任务并发出去执行,需 ...

  8. Python学习笔记——进阶篇【第九周】———线程、进程、协程篇(队列Queue和生产者消费者模型)

    Python之路,进程.线程.协程篇 本节内容 进程.与线程区别 cpu运行原理 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Ev ...

  9. 转:【Java并发编程】之七:使用synchronized获取互斥锁的几点说明

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17199201     在并发编程中,多线程同时并发访问的资源叫做临界资源,当多个线程同时访 ...

随机推荐

  1. git 不小心把某个文件给 add 了 的解决方法

    1.我不小心把这两个文件给add 进来本地仓库 2.解决 进入指令框 ,执行 git rm --cached  文件名 如下图 注意,必须指定文件否则会删除所有

  2. Java定时调度

    一.实现方式 Timer:单线程,串行: ScheduledExecutor:并行,论询,实现麻烦: Spring Scheduler:适合小任务: JcronTab:按照crontab语法编写的ja ...

  3. js对象数组多字段排序

    来源:js对象数组按照多个字段进行排序 一.数组排序 Array.sort()方法可以传入一个函数作为参数,然后依据该函数的逻辑,进行数组的排序. 一般用法:(数组元素从小大进行排序) var a = ...

  4. js对象方法

    Number对象方法 toFixed() 方法 toFixed()方法返回的是具有指定位数小数的数字的字符串表示.例如: var oNumberObject = new Number(68); ale ...

  5. 在实验中观察指针——C++ 函数参数的压栈顺序

    前言 好久没写东西了,突发奇想,写写函数参数的压栈顺序 先看看这个问题 https://q.cnblogs.com/q/137133/ 然后看我简化的代码,猜输出结果是多少? #include< ...

  6. 开启mysql外部访问(root外连)

    MySQL外部访问 mysql 默认是禁止远程连接的,你在安装mysql的系统行运行mysql -u root -p 后进入mysql 输入如下: mysql>use mysql; mysql& ...

  7. elasticsearch之集成中文分词器

    IK是基于字典的一款轻量级的中文分词工具包,可以通过elasticsearch的插件机制集成: 一.集成步骤 1.在elasticsearch的安装目录下的plugin下新建ik目录: 2.在gith ...

  8. 【golang学习记录】环境搭建

    [golang学习记录]环境搭建 一. 概述 本文是[golang学习记录]系列文章的第一篇,安装Go语言及搭建Go语言开发环境,接下来将详细记录自己学习 go 语言的过程,一方面是为了巩固自己学到的 ...

  9. day 19 C语言顺序结构基础2

    (1).算术运算符和圆括号有不同的运算优先级,对于表达式:a+b+c*(d+e),关于执行步骤,以下说法正确的是[A] (A).先执行a+b的r1,再执行(d+e)的r2,再执行c*r2的r3,最后执 ...

  10. Vue 动态设置图片路径

      大多数情况vue项目中组件是需要相互引用的,父组件引用子组件,子组件引用父组件,已达到组件重用的目的   本次记录的是父组件引用子组件,img标签定义在多个子组件中,不同或相同的父组件引用同一个子 ...