进程,线程,协程-python实现
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了进程,线程,协程-python实现,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含13008字,纯文字阅读大概需要19分钟。
内容图文
![进程,线程,协程-python实现](/upload/InfoBanner/zyjiaocheng/929/e0b3b6d5bbee49599698b28817778ed8.jpg)
进程,线程,协程-python实现
线程
创建线程
# 单线程
# import threading,time
#
# def func():
# for i in range(5):
# print("hello python")
# time.sleep(1)
#
# if __name__ == '__main__':
# 创建线程对象
# say_thread = threading.Thread(target=func)
# 启动
# say_thread.start()
# 有参数的 args= () kwargs = {}
import threading, time
def func(name, age, sex):
print(name, age, sex)
if __name__ == '__main__':
# 创建线程对象 (target = 执行目标函数名)
say_thread = threading.Thread(target=func, kwargs={'name': "老王", 'sex': '男', 'age': "18", })
# 启动
say_thread.start()
线程的性质 无序性
# .join() #线程等待 执行完一个在执行下一个
import threading, time
def func(num):
for i in range(num):
print("hello python")
time.sleep(1)
def func1(num1):
for i in range(num1):
print("hello world")
time.sleep(1)
if __name__ == '__main__':
print(threading.current_thread()) # <_MainThread(MainThread, started 11156)>
# 在demo未创建程序之前,默认存在一个主线程,这个主线程的作用为:执行程序下方的代码,当代码执行完毕后,主线程默认结束
# 创建子线程对象
print("线程开始执行")
say_thread = threading.Thread(target=func, args=(5,))
say_thread1 = threading.Thread(target=func1, args=(6,))
# 启动
say_thread.start()
say_thread.join() # 线程等待 执行完一个在执行下一个
say_thread1.start()
say_thread1.join() # 线程等待 执行完一个在执行下一个
print("线程结束执行")
多线程共享全局变量
# 多线程在共享全局变量中
# 优点:重复代码的复用率(重复利用的简写)
# 缺点:由于多线程之间出现了资源的恶意竞争问题,进而的会导致计算结果的错误和混乱
# 解决缺点的方法
# 1.0 join()
# 共享全局变量
# import threading
# alist = [11,22]
#
# def func1():
# alist.append(33)
# print(alist)
#
# def func2():
# alist.append(44)
# print(alist)
#
# if __name__ == '__main__':
# #创建子线程
# func1_thread = threading.Thread(target=func1)
# func2_thread = threading.Thread(target=func2)
# #启动
# func1_thread.start()
# func2_thread.start()
import threading
a = 0
def func1():
global a
for i in range(1000000):
a += 1
print(a)
def func2():
global a
for i in range(1000000):
a += 1
print(a)
if __name__ == '__main__':
# 创建子线程
func1_thread = threading.Thread(target=func1)
func2_thread = threading.Thread(target=func2)
# 启动
func1_thread.start()
func1_thread.join()
func2_thread.start()
锁 信号量 互斥锁 排插锁 悲观锁
全局解释器锁GIL解决了不同线程同时访问同一资源的问题,保证了同一时间,同一线程,但并没有完全解决多线程阻塞问题,还未执行完上一任务,CPU切换,蹿到下一任务执行。
使用Lock(执行完毕再执行下一个)和Semphore(给定几把锁,就在几个线程内来回切换执行)可以保证线程按顺序执行。
# 单线单核cpu 多线程之间恶意竞争资源 创造的
"""
互斥锁 排插锁 悲观锁
当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制
线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。
互斥锁为资源引入一个状态:锁定/非锁定
某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。
"""
import threading, time
a = 0
def func1(lock):
# 加锁
l.acquire()
for i in range(10000000):
global a
a += 1
print(a)
# 释放锁
l.release() # 没有释放就是死锁 如果不能自动结束 则进入僵持状态
def func2(lock):
l.acquire()
for i in range(10000000):
global a
a += 1
print(a)
l.release()
if __name__ == '__main__':
# 创建锁
l = threading.Lock()
# 创建线程
func1_thread = threading.Thread(target=func1, args=(l,))
func2_thread = threading.Thread(target=func2, args=(l,))
# 启动线程
func1_thread.start()
func2_thread.start()
进程
程序:例如xxx.py这是程序,是一个静态的
进程:一个程序运行起来后,代码+用到的资源称之为进程,它是操作系统分配资源的基本单元。
不仅可以通过线程完成多任务,进程也是可以的
进程和线程的区别?
1.进程:通俗理解一个运行起来的程序或者软件就叫做进程,
每启动一个进程,操作系统都需要给对应的进程分配运行资源,
运行资源是让线程执行代码的时候使用,所以进程是操作系统分配资源的基本单位,默认一个进程只有一个线程,这个线程是主线程
进程只提供资源,真正干活的是线程
2.0线程和进程的区别
2.1线程之间共享全局变量
2.2进程之间不共享全局变量
2.3进程:每开辟一个进程都需要向操作系统分配资源,而线程可以共享进程中的资源
2.4多进程开发比单进程开发程序的稳定性要强,因为多进程开发,某个进程死了,不会影响启动进程的运行
注意点 多进程开发需要更多资源,而多线程开发可以共享进程中的资源
Process语法结构
Process([group [, target [, name [, args [, kwargs]]]]])
? target:如果传递了函数的引用,可以任务这个子进程就执行这里的代码 tardet=
? args:给target指定的函数传递的参数,以元组的方式传递 (n,)
? kwargs:给target指定的函数传递命名参数 {“n”,”m”}
? name:给进程设定一个名字,可以不设定 name =
? group:指定进程组,大多数情况下用不到
Process创建的实例对象的常用方法:
start():启动子进程实例(创建子进程) 进程变量名.start()
? is_alive():判断主进程或子进程是否还在活着 print(进程变量名.is_alive)
? join([timeout]):是否等待子进程执行结束,或等待多少秒 进程变量名.join()
? terminate():不管任务是否完成,立即终止子进程 进程变量名.terminate()
?
守护主进程
# copy_work_process.daemon = True
Process创建的实例对象的常用属性:
name:当前进程的别名,默认为Process-N,N为从1开始递增的整数
pid:当前进程的pid(进程号) 父类的ppid
进程的格式
import multiprocessing
def func(name, age, sex):
pass
if __name__ == '__main__':
# 创建线程对象 (target = 执行目标函数名)
say_thread = multiprocessing.Process(target=func, kwargs={'name': "老王", 'sex': '男', 'age': "18", })
# 启动
say_thread.start()
# 进程之间不共享全局变量
import multiprocessing
a = [11, 22]
def fun():
a.append(33)
print(a)
def fun1():
a.append(44)
print(a)
if __name__ == '__main__':
mult_fun = multiprocessing.Process(target=fun)
mult_fun1 = multiprocessing.Process(target=fun1)
mult_fun.start()
mult_fun1.start()
判断进程是否存活
# name 给进程设定一个名字,可以不设定
# is_alive():判断主进程或子进程是否还在活着
# 有这俩种方法的demo
# import multiprocessing,time
#
# def copy_work():
# for i in range(5):
# print("正在复制中---",i+1)
# time.sleep(0.5)
#
# def copy_work2():
# for i in range(5):
# print("正在复制中---",i+1)
# time.sleep(0.5)
#
#
# if __name__ == '__main__':
# #创建子进程
# copy_work_process = multiprocessing.Process(target=copy_work,name="laowang")
# copy_work_process2 = multiprocessing.Process(target=copy_work,name="laowang")
# print(copy_work_process)
# print(copy_work_process2)
# #启动进程
# copy_work_process.start()
# copy_work_process2.start()
# # time.sleep(5) #False
# time.sleep(1) #True
# print( copy_work_process.is_alive())
# print( copy_work_process2.is_alive())
销毁子进程查看进程编号
# 主线程跟子线程同时结束的demo
# import multiprocessing,time
#
# def copy_work():
# for i in range(5):
# print("正在复制中---",i+1)
# time.sleep(0.5)
#
# def copy_work2():
# for i in range(5):
# print("正在复制中---",i+1)
# time.sleep(0.5)
#
#
# if __name__ == '__main__':
# print("主线程开始")
# #创建子进程
# copy_work_process = multiprocessing.Process(target=copy_work,name="laowang")
# copy_work_process2 = multiprocessing.Process(target=copy_work,name="laowang")
# # 方法一 守护主进程
# # copy_work_process.daemon = True
# # copy_work_process2.daemon = True
#
# #启动进程
# copy_work_process.start()
# copy_work_process2.start()
# # copy_work_process.join()
# time.sleep(1)
# print("主线程结束")
# # 方法二 销毁子进程
# copy_work_process.terminate()
# copy_work_process2.terminate()
# "子进程编号:",os.getpid()
# "主进程编号:",os.getppid()
import multiprocessing, time, os
def func(name, age, sex):
print("子进程编号:", os.getpid())
print("主进程编号:", os.getppid())
time.sleep(1)
if __name__ == '__main__':
print("启动", os.getpid())
# 创建线程对象 (target = 执行目标函数名)
say_thread = multiprocessing.Process(target=func, kwargs={'name': "老王", 'sex': '男', 'age': "18", })
# 启动
say_thread.start()
print("结束")
进程间的通信
"""
Process之间有时需要通信,可以使用multiprocessing模块的Queue实现多进程之间的数据传递,Queue本身是一个消息队列程序
初始化Queue()对象时(例如:q=Queue(5)),若括号中没有指定最大可接收的消息数量,那么就代表可接受的消息数量没有上限(直到内存的尽头);
Queue.qsize():返回当前队列包含的消息数量;
Queue.empty():如果队列为空,返回True,反之False ;
Queue.full():如果队列满了,返回True,反之False;
Queue.get([block[, timeout]]):获取队列中的一条消息,然后将其从列队中移除,block默认值为True;
Queue.put(item,[block[, timeout]]):将item消息写入队列,block默认值为True
"""
import multiprocessing, time
def fun1(queue):
for i in range(10):
if queue.full():
print("队列满了")
break
else:
queue.put(i)
print("写入的数据为:", i)
time.sleep(1)
def fun2(queue):
while True:
if queue.empty():
print("队列为空")
break
else:
ss = queue.get()
print(ss)
if __name__ == '__main__':
queue = multiprocessing.Queue(5)
fun1_process = multiprocessing.Process(target=fun1, args=(queue,))
fun2_process = multiprocessing.Process(target=fun2, args=(queue,))
fun1_process.start()
fun1_process.join()
fun2_process.start()
fun2_process.join()
进程池
进程池的作用:快速批量创建进程
from multiprocessing import *
import time, os
i = 0
def copy_work():
global i
i += 1
print("正在复制中---%d" % i)
time.sleep(3)
if __name__ == '__main__':
# 创建进程池
# 指定进程池数量表示进程池中最多一次性创建的数列
pool = Pool(3)
for i in range(10):
# 让进程池执行复制任务
# 使用同步的方式去执行任务,进程池中的需要等待其它进程执行完成后才能执行置地指定任务
# pool.apply(copy_work)
# 异步执行进程池中的进程一起执行,不会等待其他进程的执行
pool.apply_async(copy_work)
# 提示--主进程不会等待进程池把执行任务完成以后程序在退出
# 提示--进程池不在接受qi其它需要执行的任务
pool.close()
# 等待进程池把任务执行完成以后程序在退出
# 同时具有启动进程的作用
pool.join()
协程
协成,又称微线程,纤程。英文名Coroutine
协成是什么
为什么说它是一个执行单元,因为它自带cpu上下文。
这样只要在合适的时机,我们可以把一个协成 切换到另一个协成。
只要这个过程中保存或修复cpu上下文 那么程序还是可以运行的
协程,又称微线程,纤程。英文名Coroutine。
异步lo
协程的概念很早就提出来了,但直到最近几年才在某些语言(如Lua)中得到广泛应用。
协程看上去是函数,但执行过程中,在函数内部可中断,然后转而执行别的函数,在适当的时候再返回来接着执行。
python可以通过 yield/send 的方式实现协程,也可以使用第三方库中的greenlet来实现协程。
"""
"""
进程是资源分配的单位
线程是操作系统调度的单位
进程切换需要的资源很最大,效率最低
线程切换需要的资源一般,效率一般(当然了在不考虑GTL的情况下)
协成切换任务资源很小,效率高
多进程、多线程根据cpu核数不一样可能是并行的,
但是协成是在一个线程中 所以是并发
通俗的理解:
在一个线程中的某个函数,可以再任何地方保存当前函数的一些临时变量等信息
然后切换到另一个函数中执行,注意不是通过调用函数的方式做到的。
并且切换的次数以及什么时候在切换到原来的函数都由开发者自己确定
协成和线程的差异
在实现多任务时,线程千幻从系统层面远不止保存和恢复cpu上下文这么简单。
操作系统为了程序运行的高效性每个线程都由自己的缓存Cache等等数据
操作系统还会帮你做这些数据的恢复操作。所以线程的切换非常耗性能。
但是协成的切换只是单纯的操作cpu上下文,所以一秒钟切换上百万次系统都抗的住。
创建协程
"""
本质上协成只有一个线程
"""
# 在def里面只看到
import time
def fun():
while True:
print("work1")
time.sleep(0.1)
yield
def fun1():
while True:
print("work2")
time.sleep(0.1)
yield
s1 = fun()
s2 = fun1()
while True:
next(s1)
next(s2)
greenlent模块
greenlet封装的是yield,为了让程序员更好的使用协成
"""
greenlet封装的是yield,为了让程序员更好的使用协成
"""
import time
from greenlet import greenlet
def work1():
for i in range(5):
print("work1----")
time.sleep(0.1)
# 切换执行线程2
s2.switch()
def work2():
for i in range(5):
print("work2----")
time.sleep(0.1)
# 切换执行线程1
s1.switch()
# 创建协成制定对应的任务
s1 = greenlet(work1)
s2 = greenlet(work2)
# 启动并切换到指定协成执行对应的任务
s1.switch()
打补丁找猴子
import time, gevent
from gevent import monkey
monkey.patch_all()
def work1():
print("work1:", gevent.getcurrent())
for i in range(10):
print("work1---")
# gevent.sleep(0.5)
time.sleep(0.5)
def work2():
print("work2:", gevent.getcurrent())
for i in range(10):
print("work2---")
gevent.sleep(0.5)
# time.sleep(0.5)
if __name__ == '__main__':
s1 = gevent.spawn(work1)
s2 = gevent.spawn(work2)
gevent.joinall([s1, s2])
原生协程
协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存,在调度回来的时候,恢复先前保存的寄存器上下文和栈。因此协程能保留上一次调用时的状态,即所有局部状态的一个特定组合
async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await命令就是内部then命令的语法糖
import time
def job(t):
time.sleep(t)
print('用了%s' % t)
def main():
[job(t) for t in range(1,3)]
start = time.time()
main()
print(time.time()-start)
import time
import asyncio
async def job(t): # 使用 async 关键字将一个函数定义为协程
await asyncio.sleep(t) # 等待 t 秒, 期间切换执行其他任务
print('用了%s秒' % t)
async def main(loop): # 使用 async 关键字将一个函数定义为协程
tasks = [loop.create_task(job(t)) for t in range(1,3)] # 创建任务, 不立即执行
await asyncio.wait(tasks) # 执行并等待所有任务完成
start = time.time()
loop = asyncio.get_event_loop() # 建立 loop
loop.run_until_complete(main(loop)) # 执行 loop
loop.close() # 关闭 loop
print(time.time()-start)
内容总结
以上是互联网集市为您收集整理的进程,线程,协程-python实现全部内容,希望文章能够帮你解决进程,线程,协程-python实现所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。