python-多进程、线程、协程

进程线程协程分别是什么?

        进程是具有独立功能程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。

        线程是进程的一个实体,是cpu和分派的基本单位,它比进程更小的的独立运行的基本单位,线程自己基本不拥有系统资源,但它可与用属于一个进程的其他线程共享进程所拥有的全部资源。

        协程其实可以认为是比线程更小的执行单元,协程拥有自己的寄存器上下文和栈。我们把一个线程中的一个个函数叫做子程序,那么子程序在执行过程中可以中断去执行别的子程序,别的子程序也可以中断回来继续执行之前的子程序,这就是协程。

 

进程(process)

       同一个program程序可以同时存在多个process进程;

       一个cpu一次只能执行一个 process,每一个process都是相互独立的;

       同一个process下的Thread共享process的资源,如内存、变量等,不同的进程不能共享;

"""
进程不阻塞,会先执行主进程,再执行子进程
进程阻塞,join()   会等待子进程执行完,再往下执行主进程
进程守护,setDaemon(True) 主进程结束后,子进程也会随之结束;  进程阻塞和进程守护同时存在时以阻塞为主
进程通信,Queue()  采用put和get方法
进程数据共享 Manager()
"""

from multiprocessing import Process
import time
#进程阻塞
def worker(q):
    time.sleep(1)
    print(f'Process {q}')

if __name__ == '__main__':
    print('Start')
    p = Process(target=worker, args=('Process-1',))
    p.start()
    #p.join()   #阻塞
    print('Finished')


from multiprocessing import Process
#守护进程

def worker(q):
    print(f'Process {q}')

if __name__ == '__main__':
    print('Start')
    p1 = Process(daemon=True,target=worker, args=('Process-1',)) #守护进程,主代码结束守护进程随之结束
    p1.start()
    print('Finished')


from multiprocessing import Process
import os
#多进程阻塞

def worker(q):
    print(f'Process {q}  son:{os.getpid()}  father:{os.getppid()}')

if __name__ == '__main__':
    print('Start')
    p1 = Process(target=worker, args=('Process-1',))
    p2 = Process(target=worker, args=('Process-2',))
    p1.start()
    p2.start()
    print(f'Finished   son:{os.getpid()}   pycharm:{os.getppid()}')


from multiprocessing import Process, Queue
#进程通信

def p_put(q):
    q.put('hello')
    print('put',q.qsize())

def p_get(q):
    print(q.get())
    print('get',q.qsize())

if __name__ == '__main__':
    q = Queue()
    p1 = Process(target=p_put, args=(q, ))
    p2 = Process(target=p_get, args=(q, ))
    p1.start()
    p2.start()


from multiprocessing import Process,Manager
#进程数据共享

def func(mydict, mylist):
    mydict["name"] = "shuzf"  # 子进程改变dict,主进程跟着改变
    mylist.append(11)            # 子进程改变List,主进程跟着改变


if __name__ == "__main__":
    with Manager() as MG:
        mydict = MG.dict()          # 主进程与子进程共享这个字典
        mylist = MG.list(range(2))  # 主进程与子进程共享这个List

        p = Process(target=func, args=(mydict, mylist))
        p.start()
        p.join()

        print(mylist)
        print(mydict)

 

 

线程(thread)

  同一个 process进程可以同时存在多个thread线程;

       process本身不是基本执行单位,它是thread(基本执行单位)的容器;

       同一个process下的Thread共享process的资源,如内存、变量等,不同的进程不能共享;

       在多线程(Multi threading)中,两个线程如果同时存取或改变全局变量(Golbal Variable),则可能发生同步(Synchronization)的问题。如果线程之间互抢资源,则可能产生死锁(Dead Lock)。

"""
线程
线程不阻塞,会先执行主线程,再执行子线程
线程阻塞,join()  会等待子线程执行完,再往下执行主线程
守护线程,setDaemon(True) 主线程结束后,子线程也会随之结束;  线程阻塞和守护线程同时存在时以阻塞为主
线程锁,Lock()  RLock() Event()
"""
from threading import Thread
import time
#单线程

def work(q):
    time.sleep(1)
    print(f'Thread {q}')

if __name__ == '__main__':
    print("Starting Main Thread")
    t=Thread(target=work,args=("Thread-1",))
    t.start()
    #t.join()
    print("Exiting Main Thread")



from threading import Thread
import time
#守护线程

def work(q):
    time.sleep(1)
    print(f'Thread {q}')

if __name__ == '__main__':
    print("Starting Main Thread")
    t=Thread(target=work,args=("Thread-1",))
    t.setDaemon(True)
    t.start()
    t.join()
    print("Exiting Main Thread")


from threading import Thread
import time
#多线程

def work(q):
    time.sleep(1)
    print(f'Thread {q}')

if __name__ == '__main__':
    print("Starting Main Thread")
    t1=Thread(target=work,args=("Thread-1",))
    t2=Thread(target=work,args=("Thread-2",))
    t1.start()
    t2.start()
    # t1.join()
    # t2.join()
    print("Exiting Main Thread")


from threading import Thread
#多线程方式2
class myThread(Thread):
    def __init__(self,threadName):
        super().__init__()
        self.threadName=threadName

    def run(self):
        print(f'Thread runing {self.threadName}')

if __name__ == "__main__":
    threads = [myThread("Thread-1"),myThread("Thread-2"),myThread("Thread-3")]
    for i in threads: i.start()     # 开起子线程
    for i in threads: i.join()      # join()子线程执行完,主线程才恢复到运行
    print ("Exiting Main Thread")


from threading import Thread
import threading,time
#线程锁(互斥锁、递归锁)

def work(q):
    print(f"Thread starting {q}")
    threadLock.acquire()  # 获得锁
    time.sleep(1)
    print(f'Thread runing {q}')
    threadLock.release()  # 释放锁
    print(f"Thread exiting {q}")

if __name__ == '__main__':
    print("Starting Main Thread")
    t1=Thread(target=work,args=("Thread-1",))
    t2=Thread(target=work,args=("Thread-2",))
    threadLock = threading.Lock()   # 创建互斥锁(线程1进入锁后,只有释放锁才能执行线程2)
    #threadLock = threading.RLock()  # 创建递归锁(线程1进入锁后,只有释放锁才能执行线程2)
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print("Exiting Main Thread")



from threading import Thread
import threading,time
#线程锁(信号量)

def work(q):
    print(f"Thread starting {q}")
    if threadLock.acquire():  # 获得锁
        time.sleep(1)
        print(f'Thread runing {q}')
        threadLock.release()  # 释放锁
        print(f"Thread exiting {q}")

if __name__ == '__main__':
    print("Starting Main Thread")
    t1=Thread(target=work,args=("Thread-1",))
    t2=Thread(target=work,args=("Thread-2",))
    t3=Thread(target=work,args=("Thread-3",))
    threadLock  = threading.BoundedSemaphore(2)  #创建信号量(该锁用于限制线程的并发量)
    t1.start()
    t2.start()
    t3.start()
    t1.join()
    t2.join()
    t3.join()
    print("Exiting Main Thread")


import time
from threading import Thread,Event
#线程通信(Event)

def foo(event):
    print('wait server...')
    event.wait()    #括号里可以带数字执行,数字表示等待的秒数,不带数字表示一直阻塞状态
    print('connect to server')
def start(event):
    print('start server successful')
    time.sleep(1)
    event.set()     #默认为False,set一次表示True,所以子线程里的foo函数解除阻塞状态继续执行

if __name__ == '__main__':
    event = Event()
    t1=Thread(target=foo,args=(event,))
    t2=Thread(target=start,args=(event,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()


import queue
from threading import Thread
#queue 线程队列

def put(q):
    q.put('hello')
    print('put',q.qsize())

def get(q):
    print(q.get())
    print('get',q.qsize())

if __name__ == '__main__':
    q = queue.Queue()
    t1=Thread(target=put,args=(q,))
    t2=Thread(target=get,args=(q,))
    t1.start()
    t2.start()

 

协程(coroutine)

  协程,又称微线程,英文名Coroutine。协程是一种用户态的轻量级线程。

  我们把一个线程中的一个个函数叫做子程序,那么子程序在执行过程中可以中断去执行别的子程序;别的子程序也可以中断回来继续执行之前的子程序,这就是协程。

  协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。

import grequests
import requests
import gevent
import asyncio,aiohttp,time,os
from functools import wraps #@wraps可以保证装饰器修饰的函数的name的值保持不变

url1 = "http://www.baidu.com" url2 ="http://42.192.162.8:9001/api/time" def runTime(func): """ 修饰函数(统计函数运行时间)-无参数、有参数 @param func: 目标函数 @return: """ @wraps(func) #@wraps不改变使用装饰器原有函数的结构(如name, doc) def inner(*args, **kwargs): s = time.time() func(*args, **kwargs) print(f'--> {func.__name__} RUN TIME: <{(time.time() - s)}> ') #print('--> task (pid={}) is running '.format(os.getpid())) return inner @runTime def test_requests(num): urls = [url1 forin range(num)] req = [requests.get(url=url, timeout=5) for url in urls] print(req) @runTime def test_grequests(num): urls = [url1 forin range(num)] req = [grequests.request("GET", url, timeout=5) for url in urls] resp = grequests.map(req, size=100) #此处map的requests参数是装有实例化请求对象的列表,其返回值也是列表, size参数可以控制并发的数量 #for res in resp: print(res) #print(res.text) print(resp) async def fetch(url,sem): async with sem: async with aiohttp.ClientSession() as session: async with session.get(url, timeout=5) as res: pass #print(res.status) @runTime def test_asyncio(num): sem =asyncio.Semaphore(100) #asyncio控制并发数 tasks = [fetch(url1,sem) for i in range(num)] loop = asyncio.get_event_loop() resp = loop.run_until_complete(asyncio.wait(tasks)) #loop.run_until_complete将task放到loop中,进行事件循环,这里必须传入的是一个list loop.close() print(resp) def func(url): res = requests.get(url=url,timeout=5) #print(res) @runTime def test_gevent(num): tasks= [gevent.spawn(func,url1) for i in range(num)] resp = gevent.joinall(tasks) print(resp) if __name__ == "__main__": #test_requests(10) #test_grequests(10) #test_asyncio(10) test_gevent(10)

 

用yield实现协程

"""
通过调用send方法和yield互相切换,实现协程的功能
"""
import time
def consume():
    r=''
    while True:
        n = yield r
        if n is None: return
        print('[consumer] 消费 %s' % n)
        time.sleep(1)
        r = 'well received'

def produce(c:object,n:int=0):
    c.send(None)  #启动生成器,第一次n为None
    while n < 5:
        n = n + 1
        print('[producer] 生产 %s' % n)
        r = c.send(n)  #切换到consume执行
        print('[producer] return: %s' % r)
    c.close()

if __name__=='__main__':
    c = consume()
    produce(c)

 

posted @ 2021-10-25 14:24  南方的墙  阅读(104)  评论(0编辑  收藏  举报