灵虚御风
醉饮千觞不知愁,忘川来生空余恨!

导航

 
并发编程
    计算机发展史

    进程理论

    创建进程的两种方式(******)

    进程方法join

    进程对象及其他方法

    进程间数据互相隔离

    守护进程

    互斥锁(*****)



多道技术:
    1.空间上的复用
        多个程序共用一套计算机硬件

    2.时间上的复用
        切换+保存状态
            1.当一个程序遇到IO操作 操作系统会剥夺该程序的CPU执行权限(提高了CPU利用率,并且也不影响程序的执行效率)
            2.当一个程序长时间占用CPU操作系统


    并发:看起来同时运行就可以
    并行:真正意义上的同时执行
        单核的计算机能不能实现并发,但是可以并发

     程序:一坨代码
     进程:正在运行的程序

    同步异步:表示的是任务提交方式,
        同步:任务提交后,原地等待的任务执行 并拿到返回结果才走,期间不做任何事(程序层面的表现就是卡注了)
        异步:任务提交后,不再原地等待,而是继续执行下一步代码(结果是要通过其他的方式获取)

        阻塞非阻塞:表示的程序 运行的状态
            阻塞:阻塞态
            非阻塞:就绪态 运行态

    强调:同步异步 阻塞非阻塞是两对概念不能混为一谈

    僵尸进程 与 孤儿进程
        父进程回收子进程资源的两种方式
            1.join方法
            2.父进程正常死亡
    孤儿进程
        子进程没死 父进程意外死亡

        针对linux 会有儿童福利院(init) 如果父进程意外死亡 它所创建的子进程都会被福利院收养

    守护进程:
        设置守护进程,p.daemon = True 这一句话必须放在start语句之前 否则报错

    互斥锁:
        当多个进程操作同一份数据时,会造成数据的错乱
        这个时候必须加锁处理
            将并发变成串行
                虽然降低了效率但是提高了数据的安全

            ps:
                1.锁不要轻易使用 : 容易造成死锁现象
                2.只在处理数据的部分加锁,不要在全局加锁

             锁必须在主进程中产生去子进程中使用
30.进程方法与互斥锁
from multiprocessing import Process
import time
import os
def test(name):
    print(f'{name} is running')
    print('son run')
    print(f'son:{os.getpid()}')  # 求子进程
    print(f'father:{os.getppid()}')
    print('son over')
    time.sleep(3)
    print(f'{name} is over')

" windows 创建进程 会将代码以模块的模式从上往下执行一遍" \
"linux会直接将代码完完整整的拷贝一份"
"""
windows创建进程一定要在if __name__ == '__main__':代码块内创建  否则报错
"""

if __name__ == '__main__':
    p = Process(target=test,args=('egon',)) # 创建一个进程对象
    print(os.getpid())  # 求父进程
    p.start()  # 告诉操作系统帮你创作一个进程
    print('')
"""
11584
主
egon is running
son run
son:10952
father:11584
son over
egon is over

"""
"""
创建进程一的方法 : 直接实例化Process,将要执行target传入 
"""
"""
创建进程 就是在内存中重新开辟一块内存空间 将允许产生的代码丢进去
一个进程对应在内存就是一个独立的内存空间

进程与进程之间数据是隔离的 无法直接交互
但是可以通过某些技术实现间接交互
"""
1.创建进程的两种方式 方法一.py
""""""
"""创建进程方法二:继承Process类,覆盖run方法,将任务放入run方法中"""
from multiprocessing import Process
import time
import os
class MyProcess(Process):
    def __init__(self,name):
        super().__init__()
        self.name = name
    def run(self):
        print(f'{self.name} is running')
        print(f'son run:{os.getpid()}')
        time.sleep(3)
        print(f'father run:{os.getppid()}')
        print(f'{self.name} is over')


if __name__ == '__main__':
    p = MyProcess('llx')
    p.start()
    print('')
    print(os.getpid())

"""
主
2460
llx is running
son run:11516
father run:2460
llx is over

"""
1.2.创建进程的两种方式 方法二.py
from multiprocessing import Process
import time

def test(name,i):
    print(f'{name} is running')
    time.sleep(i)
    print(f'{name} is over')

if __name__ == '__main__':
    p_list = []
    # for i in range(3):
    #     p = Process(target=test,args=(f'进程{i}',i))
    #     p.start()
    #     p_list.append(p)
    # for p in p_list:
    #     p.join()
    # print(p_list)
# """
# [<Process(Process-1, started)>, <Process(Process-2, started)>, <Process(Process-3, started)>]
#
# """
# """
# 进程0 is running
# 进程0 is over
# 进程1 is running
# 进程2 is running
# 进程1 is over
# 进程2 is over
# """
    p = Process(target=test,args=('egon',1))
    p1 = Process(target=test,args=('kevin',2))
    p2 = Process(target=test,args=('jason',3))
    start_time = time.time()
    p.start()  # 仅仅是告诉操作系统帮助你创建一个进程 至于这个进程是什么时候创建 操作系统 随机决定
    p1.start()
    p2.start()
    p2.join()
    p.join()
    p1.join()
    # 主进程代码等待子进程运行结束 才继续运行
    # p.join()  # 主进程代码等待子进程运行结束
    print('')
    print(time.time()-start_time)

    """
egon is running
kevin is running
egon is over
jason is running
kevin is over
jason is over
主
15.402495861053467
    """
2.join方法.py
from multiprocessing import Process
import time

money = 100

def test():
    global money
    money = 888888888888

if __name__ == '__main__':
    p = Process(target=test)
    p.start()
    p.join()
    print(money) # 100
3.进程间数据是隔离的.py
from multiprocessing import Process,current_process
import os
import time

def test(name):
    print(f'{current_process().pid} is running')
    print(f'{name} is running',f'子进程{os.getpid()}',f'父进程{os.getppid()}')
    time.sleep(3)
    print(f'{name} is over')

if __name__ == '__main__':
    p = Process(target=test,args=('egon',))
    p.start()
    p.terminate() # 杀死当前进程,其实是告诉操作系统帮你杀死一个进程
    time.sleep(0.1)
    print(p.is_alive())  # 判断当前进程是否存在
    print('',current_process().pid)
    print('',os.getpid(),f'主主进程{os.getppid()}')



"""
True
主 13240
主 13240 主主进程2236
15708 is running
egon is running 子进程15708 父进程13240
egon is over

# 杀死当前进程后
False
主 14320
主 14320 主主进程2236

"""
"""
1.tasklist


2.D:\面试整理\重新开始\8.json socket 进程 线程 并发 锁(27-33)>tasklist| findstr 2236
pycharm64.exe                 2236 Console                   90  1,153,332 K

"""
4.进程对象及其他方法.py
from multiprocessing import Process
import time

def test(name):
    print(f'{name}总管正常活着')
    time.sleep(3)
    print(f'{name}总管正常死亡')

if __name__ == '__main__':
    p = Process(target=test,args=('egon',))
    # p.daemon = True  # # 将该进程设置为守护进程   这一句话必须放在start语句之前 否则报错
    p.start()
    time.sleep(0.1)
    print('主进程 结束')

"""
守护进程设置前:
主进程 结束
egon总管正常活着
egon总管正常死亡

守护进程设置后:
主进程 结束
"""
5.守护进程.py
from multiprocessing import Process
"""导入锁的模块"""
from multiprocessing import Lock
import time
import json

"""查票"""
def search(i):
    with open('data','r',encoding='utf-8')as f:
        data = f.read()
    t_d = json.loads(data)
    print(f'用户{i}查询余票为:{t_d.get("ticket")}')

"""买票"""
def buy(i):
    with open('data','r',encoding='utf-8')as f:
        data = f.read()
    t_d = json.loads(data)
    time.sleep(1)
    if t_d.get('ticket') > 0:
        """票数减一"""
        t_d['ticket'] -= 1
        """更新票数"""
        with open('data','w',encoding='utf-8')as f:
            json.dump(t_d,f)
        print(f'用户{i}抢票成功')
    else:
        print('没票了')


def run(i,mutex):
    search(i)
    mutex.acquire() # 抢锁
    """
    只要有人抢到了锁 其他人必须等待该人释放锁
    """
    buy(i)
    mutex.release() # 释放锁

if __name__ == '__main__':
    mutex = Lock() # 生成一把锁
    for i in range(10):
        p = Process(target=run,args=(i,mutex))
        p.start()
        p.join()
6.互斥锁.py
""""""
"""
队列:先进先出
堆栈:先进后出
"""
from multiprocessing import Queue
q = Queue(5)   # 括号内可以传参数 表示的是这个队列的最大存储数
# 往队列中添加数据
q.put(1)
q.put(2)
q.put(3)
print(q.full()) # 判断队列是否满了
q.put(4)
q.put(5)
# print(q.full())
# q.put(6)  # 当队列满了之后 再放入数据 不会报错 会原地等待 直到队列中有数据被取走(阻塞态)
print(q.get())
print(q.get())
print(q.get())
print(q.get())
print(q.get())
print(q.empty()) # # 判断队列中的数据是否取完
# print(q.get_nowait()) # # 取值 没有值不等待直接报错
7.进程间通信.py
from multiprocessing import Process,Queue

def producer(q):
    q.put('hello llx')

def consumer(q):
    print(q.get())

if __name__ == '__main__':
    q = Queue()
    p = Process(target=producer,args=(q,))
    c = Process(target=consumer,args=(q,))
    p.start()
    c.start()
"""
子进程放数据 主进程获取数据
两个子进程相互放 取数据
"""
"""hello llx"""
8 进程间通信IPC机制.py
""""""
"""
生产者:生产/制造数据的
消费者:消费/处理数据的
例子:做包子的,买包子的
        1.做包子远比买包子的多
        2.做包子的远比包子的少
        供需不平衡的问题
"""
from multiprocessing import Process,Queue,JoinableQueue
import time
import random

def producer(name,food,q):
    for i in range(10):
        data = f'{name}生产了{food}编号{i}'
        time.sleep(random.random())
        q.put(data)
        print(data)



def consumer(name,q):
    while True:
        data = q.get()
        if data == None:break
        print(f'{name}吃了{data}')
        time.sleep(random.random())
        q.task_done()  # 告诉队列你已经从队列中取出一个数据并且处理完毕了


if __name__ == '__main__':
    q = JoinableQueue()

    p = Process(target=producer,args=('主厨llx','',q))
    p1 = Process(target=producer,args=('配菜llw','凉菜',q))
    c = Process(target=consumer,args=('刘利兴',q))
    c1 = Process(target=consumer,args=('刘利伟',q))
    p.start()
    p1.start()
    c.daemon = True
    c1.daemon = True
    c.start()
    c1.start()
    p.join()
    p1.join()

    q.join()  # 等到队列中数据全部取出
9.生产者与消费者模型.py

 

posted on 2022-03-28 15:41  没有如果,只看将来  阅读(19)  评论(0编辑  收藏  举报