当前位置: 首页 > news >正文

并发编程

计算机基础

io操作:

复制代码
 i input  输入 相对内存 进入内存
    # read
    # recv
    # input 
    # load
o output 输出 相对内存 从内存出去
    # write
    # send
    # dump
复制代码

多道操作系统:

  • 提高了cpu的利用率
  • 第一次出现了一个概念:任务状态的保存
  • 数据的隔离的概念(由于同时在执行的多个程序之间的数据不能混为一谈)

单处理机系统中的多道程序运行是的特点:

  • 多道:计算机内存中同时存放几道相互独立的程序
  • 宏观上并行:同时进入系统的几道相互独立的程序
  • 微观上串行:实际上,各道程序轮流的用cpu,并交替运行

进程:

  • 是计算机中资源分配的最小单位
  • 并且进程与进程之间的数据是隔离的

 

 

 

 

 

 

 

 

同步和异步:

  • 同步:有几件事情,先做一件,做完一件在做一件
  • 异步:有几件事情,同时完成
  • 阻塞:程序由于不符合某个条件或者要等待某个条件满足在一个某一个地方进入等待状态
  • 非阻塞:所有不阻塞的程序
  • 如果想让阻塞的程序不阻塞,就调用setblocking()

同步阻塞\非阻塞和异步阻塞\非阻塞:

  View Code

进程模块

进程id:

  • os.getpid()  ---->获取当前进程号
  • os.getppid() ----->获取当期父进程号

在python代码中开启子进程:

  开启子进程

进程中的一些操作:

  • 子进程对于主进程中的全局变量的修改是不生效的
  • join的功能就是阻塞  只有一个条件是能够让我继续执行 这个条件就是子进程结束

 join操作的扩展:

  • join(timeout = 时间)  如果没有写这个参数 join会一直阻塞到子进程结束 如果设置的超市时间,那么意味着如果不足时间(你自己写的)子进程结束了,程序结束阻塞,如果超过时间还没有结束,那么也结束阻塞
  • terminate() 也可以强制结束一个子进程

守护进程:

  • 设置子进程为守护进程,守护进程会随着主进程的代码结束而结束
  • 由于主进程要负责给所有的子进程收尸,所以主进程必须是最后结束,守护进程只能在主进程的代码结束之后就认为主进程结束了
  • 守护进程在主进程的代码结束之后就结束了,不会等待其他子进程结束
  • 守护进程会等待主进程的代码结束而结束,不会等待其他子进程的结束
  • 要想守护进程等待其他子进程,只需要在主进程中加上join

操作多个子进程的结束和join阻塞:

复制代码
# lst = []
# for i in range(n):
#     p = Process()
#     lst.append(p)
#     p.start()
# for p in lst:
    # p.join()
    # p.terminate()
复制代码

开启子进程的另一种方式:

复制代码
import os
from multiprocessing import Process
class Myprocess(Process):
    def __init__(self,参数):
        super().__init__()
        self.一个属性 = 参数
    def run(self):
        print(子进程中要执行的代码)
if __name__ == '__main__':
    conn = "一个链接"
    mp = Myprocess(conn)
    mp.start()
复制代码

锁的概念:

复制代码
import json
import time
from multiprocessing import Process,Lock

def search(name):
    '''查询余票的功能'''
    with open('ticket') as f:
        dic = json.load(f)
        print(name , dic['count'])

def buy(name):
    with open('ticket') as f:
        dic = json.load(f)
    time.sleep(0.1)
    if dic['count'] > 0:
        print(name,'买到票了')
        dic['count'] -=1
    time.sleep(0.1)
    with open('ticket','w') as f:
        json.dump(dic,f)

def get_ticket(name,lock):
    search(name)
    lock.acquire()  # 只有第一个到达的进程才能获取锁,剩下的其他人都需要在这里阻塞
    buy(name)
    lock.release()  # 有一个人还锁,会有一个人再结束阻塞拿到钥匙

if __name__ == '__main__':
    lock = Lock()
    for i in range(10):
        p = Process(target=get_ticket,args=('name%s'%i,lock))
        p.start()
复制代码

 信号量:

  • 对于锁  保证一段代码同一时刻只能有一个进程执行
  • 对于信号量 保证一段代码同一时刻只能有n个进程执行
  • 信号量 :锁+计数器实现的
  关于信号量的事例

事件:

  • Event  事件类
  • 事件本身就带着标识:False
  • wait 阻塞 它的阻塞条件是 对象标识为False 结束阻塞条件是True
  • 与对象标识相关的
    • set 将对象的标识设置为True
    • clear 将对象的标识设置为False
    • is_set 查看对象的标识是否为True

 

复制代码
# import time
# import random
# from multiprocessing import Event,Process
# def traffic_light(e):
#     print('\033[1;31m红灯亮\033[0m')
#     while True:
#         time.sleep(2)
#         if e.is_set():   # 如果当前是绿灯
#             print('\033[1;31m红灯亮\033[0m') # 先打印红灯亮
#             e.clear()                        # 再把灯改成红色
#         else :           # 当前是红灯
#             print('\033[1;32m绿灯亮\033[0m') # 先打印绿灯亮
#             e.set()                          # 再把灯变绿色
#
# def car(e,carname):
#     if not e.is_set():
#         print('%s正在等待通过'%carname)
#         e.wait()
#     print('%s正在通过'%carname)
#
# if __name__ == '__main__':
#     e = Event()
#     p = Process(target=traffic_light,args = (e,))
#     p.start()
#     for i in range(100):
#         time.sleep(random.randrange(0,3))
#         p = Process(target=car, args=(e,'car%s'%i))
#         p.start()
复制代码

进程之间的通信(IPC):

  • 进程间的通信 Inter-Process Communication
  • 实现进程之间通信的两种机制: 1:管道 Pipe 2.队列:Queue  
复制代码
from multiprocessing import Queue,Process
def  consumer(q):
    print('子进程':,q.get())
if __name__ == '__main__':
    q = Queue()
    p = Process(target = consumer,args = (q,))
    p.start()
    q.put("hello,world")
复制代码

生产者消费者模型:

复制代码
import time
from multiprocessing import Queue,Process

def producer(name,food,num,q):
    '''生产者'''
    for i in range(num):
        time.sleep(0.3)
        foodi = food + str(i)
        print('%s生产了%s'%(name,foodi))
        q.put(foodi)

def consumer(name,q):
    while True:
        food = q.get()   # 等待接收数据
        if food == None:break
        print('%s吃了%s'%(name,food))
        time.sleep(1)

if __name__ == '__main__':
    q = Queue(maxsize=10)
    p1 = Process(target=producer,args = ('宝元','泔水',20,q))
    p2 = Process(target=producer,args = ('战山','鱼刺',10,q))
    c1 = Process(target=consumer, args=('alex', q))
    c2 = Process(target=consumer, args=('wusir', q))
    p1.start()   # 开始生产
    p2.start()   # 开始生产
    c1.start()
    c2.start()
    p1.join()    # 生产者结束生产了
    p2.join()    # 生产者结束生产了
    q.put(None)  # put None 操作永远放在所有的生产者结束生产之后
    q.put(None) 
复制代码

joinablequeue实现的生产者消费者模型:

复制代码
import  time
from multiprocessing import JoinableQueue,Process

def consumer(name,q):
    while True:
        food = q.get()
        time.sleep(1)
        print('%s消费了%s'%(name,food))
        q.task_done()

def producer(name,food,num,q):
    '''生产者'''
    for i in range(num):
        time.sleep(0.3)
        foodi = food + str(i)
        print('%s生产了%s'%(name,foodi))
        q.put(foodi)
    q.join()   # 消费者消费完毕之后会结束阻塞
if __name__ == '__main__':
    q = JoinableQueue()
    p1 = Process(target=producer, args=('宝元', '泔水', 20, q))
    c1 = Process(target=consumer, args=('alex', q))
    c2 = Process(target=consumer, args=('wusir', q))
    c1.daemon = True
    c2.daemon = True
    p1.start()
    c1.start()
    c2.start()
    p1.join()
复制代码

进程之间的数据共享:

复制代码
from multiprocessing import Manager,Process,Lock
def work(d,lock):
    # with lock: #不加锁而操作共享的数据,肯定会出现数据错乱
    #     d['count']-=1
    lock.acquire()
    d['count'] -= 1
    lock.release()

if __name__ == '__main__':
    lock=Lock()
    m = Manager()
    dic=m.dict({'count':100})
    p_l=[]
    for i in range(100):
        p=Process(target=work,args=(dic,lock))
        p_l.append(p)
        p.start()
    for p in p_l:
        p.join()
    print(dic)
复制代码
  • Manager是一个类 内部有一些数据类型能够实现数据类型能够实现进程之间的数据共享dict,list这样的数据 内部的数字进行自加 自减 是会引起数据不安全的,这种情况下需要我们手动加锁完成 因此 我们一般情况下 不适用这种方式来进行进程之间的通信 我们宁可使用Queue队列或者其他消息中间件来实现消息的传递 保证数据的安全性

进程池:

  • 为什么要使用进程池

    • 任务很多 cpu个数*五个任务以上

    • 为了节省创建和销毁进程的时间和操作系统的资源
  • 一般进程池中进程的个数:

    • cpu的1-2倍
    • 如果是高计算,完全没有io和,那么就用cpu的个数
    • 随着io操作越多,可能池中的进程个数也可以相应增加 

转载于:https://www.cnblogs.com/hard-up/p/10099287.html

相关文章:

  • Vscode的使用
  • VS2015调用Matlab2017a环境配置(转载)
  • 遍历器 for...of 循环
  • iOS开发实战之搜索控制器UISearchController使用
  • 饭卡
  • mysql索引原理与查询优化
  • protobuf中文教程(第一篇)
  • ASP.Net Core The type initializer for 'Gdip' threw an exception
  • js变量前的+是什么意思
  • ActiveMQ消息的消费原理
  • 下拉框搜索插件chosen
  • Vue -computed传参数
  • bzoj 2535 bzoj 2109 [Noi2010]Plane 航空管制——贪心
  • redis面试题集錦
  • 安卓创始人计划推出能帮你约会的AI手机
  • 深入了解以太坊
  • “寒冬”下的金三银四跳槽季来了,帮你客观分析一下局面
  • 【从零开始安装kubernetes-1.7.3】2.flannel、docker以及Harbor的配置以及作用
  • 2017届校招提前批面试回顾
  • Brief introduction of how to 'Call, Apply and Bind'
  • iOS高仿微信项目、阴影圆角渐变色效果、卡片动画、波浪动画、路由框架等源码...
  • Java|序列化异常StreamCorruptedException的解决方法
  • Java方法详解
  • JS笔记四:作用域、变量(函数)提升
  • js面向对象
  • Mocha测试初探
  • ReactNative开发常用的三方模块
  • React的组件模式
  • 官方新出的 Kotlin 扩展库 KTX,到底帮你干了什么?
  • 将 Measurements 和 Units 应用到物理学
  • 区块链分支循环
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 移动端 h5开发相关内容总结(三)
  • 以太坊客户端Geth命令参数详解
  • Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...
  • 京东物流联手山西图灵打造智能供应链,让阅读更有趣 ...
  • ​LeetCode解法汇总2808. 使循环数组所有元素相等的最少秒数
  • ### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
  • (4)事件处理——(6)给.ready()回调函数传递一个参数(Passing an argument to the .ready() callback)...
  • (Forward) Music Player: From UI Proposal to Code
  • (JS基础)String 类型
  • (保姆级教程)Mysql中索引、触发器、存储过程、存储函数的概念、作用,以及如何使用索引、存储过程,代码操作演示
  • (更新)A股上市公司华证ESG评级得分稳健性校验ESG得分年均值中位数(2009-2023年.12)
  • (含react-draggable库以及相关BUG如何解决)固定在左上方某盒子内(如按钮)添加可拖动功能,使用react hook语法实现
  • (三)Pytorch快速搭建卷积神经网络模型实现手写数字识别(代码+详细注解)
  • (四)Android布局类型(线性布局LinearLayout)
  • (转)利用PHP的debug_backtrace函数,实现PHP文件权限管理、动态加载 【反射】...
  • (轉貼) 蒼井そら挑戰筋肉擂台 (Misc)
  • .babyk勒索病毒解析:恶意更新如何威胁您的数据安全
  • .libPaths()设置包加载目录
  • .NET(C#) Internals: as a developer, .net framework in my eyes
  • .NET/C# 编译期间能确定的相同字符串,在运行期间是相同的实例
  • .NET/C# 解压 Zip 文件时出现异常:System.IO.InvalidDataException: 找不到中央目录结尾记录。
  • .NET/C# 中你可以在代码中写多个 Main 函数,然后按需要随时切换
  • .net流程开发平台的一些难点(1)