python中的多进程,多线程,死锁,多协程

本人根据自己的理解来总结的,如果有错误的地方还请各位大佬指正,谢谢了.

进程:程序是计算机可执行的二进制数据,只有被操作系统调用的时候才开始它们的生命周期.进程就是程序的一次执行,拥有自己的地址空间,内存,进程id(pid),数据栈及其他记录其运行轨迹的辅助数据;最小的资源分配单元.

多进程:使用多进程主要是为了实现多任务,提高效率;在python 中的multiprocessing库中Process类可用来创建子进程,子进程可以创建多个,但是全局变量在多个进程中不能共享,也就是进程之间资源不能共享,因为它们都有自己的内存和数据栈;但是可以通过多进程库提供的Queue队列实现进程间的通信.

import os
import time
from multiprocessing import Process
num = 100
def run1():
    global num
    print("子进程开始")
    time.sleep(2)
    print(num+100)
    print("子进程结束")
if __name__ == "__main__":
  #可以使用os.getpid()获得当前进程的id
  #可以用os.getppid()获得当前进程父继承id.
    print("主进程启动,进程id为:%s"%(os.getpid()))
    # 创建一个子进程,可以创建多个进程
    p = Process(target=run1)
    p.start()
    #进程阻塞,作用:等子进程结束,父进程再结束
    p.join()
    time.sleep(1)
    print(num)
    print("主进程结束")
#输出结果:
主进程启动,进程id为:4976
子进程开始
200
子进程结束
100
主进程结束
#进程间的通信,需要用到队列
import os
import random
import time
from multiprocessing import Process,Queue
def write(q):
    print("写进程开始-%s"%(os.getpid()))
    for chr in ["A","B","C","D","E",]:
        q.put(chr)
        time.sleep(1)
    print("写进程结束")
def read(q):
    print("读进程开启-%s"%(os.getpid()))
    while True:
        value = q.get(True)
        print(value)
    print("读进程结束")
if __name__ == "__main__":
    print("主进程开始")
    # 在主进程中创建进程队列
    q = Queue()
    #创建读写进程
    pw = Process(target=write,args=(q,))
    pr = Process(target=read,args=(q,))
    #启动读写进程
    pw.start()
    pr.start()
    # 写进程结束
    pw.join()
    #pr进程使被动地结束,在写进程结束后,读进程被强制结束
    pr.terminate()
    print("主进程结束")
#输出结果:
主进程开始
写进程开始-8768
读进程开启-7220
A
B
C
D
E
写进程结束
主进程结束

线程:线程是程序中一个单一的顺序控制流程。进程内有一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指令运行时的程序的调度单位;有就绪,阻塞,运行三种状态;又叫轻型的进程,进程可以共享进程的资源,最小的执行单元.

多线程:在一个进程中同时运行多个不同的子任务,就是多线程.线程之间可以共享进程的资源,但是如果多个进程在对同一个变量进行操作,会把结果给整乱套;由此衍生出了线程锁,阻止多线程的并发执行,确保一个线程可以从头执行到结束,相当于局部多线程,上锁部分以单线程来执行.

  • 死锁:两个或两个以上的进程或者线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去,都处于无限的相互等待状态.;

  • 死锁会导致线程挂起,只有通过操作系统取强制终止.

#线程的危害,由于共享资源,对一个变量进行操作胡出错.
import threading
num = 100
#创建线程锁
lock = threading.Lock()
#可以为每个线程绑定一个数据库连接/http请求/用户信息,区分开对变量进行操作:需要声明:local.变量名=值
local = threading.local()
#事件,event.wait()用于事件的阻塞,event.clear()用于事件的重置
event = threading.Event()
def run():
    print("%s线程开始"%(threading.current_thread().name))
    global num
    for i in range(1000000):
        #上锁,上锁后运行结果是正确的
        lock.acquire()
        try:
        	num += 100
        	num -= 100
        finally:
            #无论如何都要释放锁,否则会导致死锁
            lock.release()
           '''
        另外一种上锁方式,推荐使用这种,减小忘记释放锁的情况
        with lock:
            num += 100
        	num -= 100
           '''
    print('%s线程结束'%(threading.current_thread().name))

if __name__ == "__main__":
    print("进程开始了")
    # 创建第一个线程
    t1 = threading.Thread(target=run,name="线程1")
    t2 = threading.Thread(target=run,name="线程2")
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print("num=%s"%(num))
    print("进程结束了")
#输出结果:
进程开始了
线程1线程开始
线程2线程开始
线程1线程结束
线程2线程结束
num=300
进程结束了

 

#多进程调度器,由于多线程执行后的结果有随机性,所以要按照一定顺序的话需要一个多线程调度器,这个只是简单的,复杂一点还需要深入研究
import threading
import time
#创建调度对像
con = threading.Condition()
def run1():
    with con:
        for i in range(0,10,2):
            print(i)
            time.sleep(1)
            #执行完一个,等待,让线程2进行
            con.wait()
            #通知线程2
            con.notify()
def run2():
    with con:
        for i in range(1, 10, 2):
            print(i)
            time.sleep(1)
            #执行完后通知线程1
            con.notify()
            #处于等待状态
            con.wait()
if  __name__ == "__main__":
    threading.Thread(target=run1,name=threading.current_thread().name).start()
    threading.Thread(target=run2, name=threading.current_thread().name).start()
#输出结果:
0
1
2
3
4
5
6
7
8
9

协程: 是为非抢占式多任务产生子程序的计算机程序组件,协程允许不同入口点在不同位置暂停或开始执行程序.看上去是子程序,但是可以在子程序内部中断子程序,转而去执行别的子程序,也就是cpu中断.与线程相比,协程的效率极高,因为只有一个线程,不会发生变量的冲突,共享资源不需要加锁,只需要判断状态.python对协程的支持是通过generator(生成器)实现的,有点类似有多层函数的引用,一层一层执行下去,多协程消耗的资源极少.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值