Python并发实践_01_线程与进程初探
进程与线程
在多任务处理中,每一个任务都有自己的进程,一个任务会有很多子任务,这些在进程中开启线程来执行这些子任务。一般来说,可以将独立调度、分配的基本单元作为线程运行,而进程是资源拥有的基本单位。
python支持多进程multiprocessing,以及多线程threading。
多进程
os.fork()函数可以开启一个进程。该函数会返回两次值,分别在父进程中返回子进程的ID,而在子进程中永远返回0。
os.getpid()函数可以返回进程的ID。os.getppid()则可以返回父进程的ID。
通过os.fork(),可以随时开启一个进程并且返回进程ID,以及使用os.getpid()、os.getppid()函数,可以任意时刻查看目前所在的进程ID,以及父进程的ID。
fork()函数只在unix/linux下有效,windows并不支持fork(),使用multiprocessing.Process类提供的多进程调用更加完整地反映整个过程。
from multiprocessing imort Process
def proc_worker(args):
pass
def main():
p = Process(target=proc_worker,args=(some_args,))
p.start()
p.join()
Process实例指定子进程运行的函数以及相关参数,并且start()和join()方法可以控制进程的开始和等待。
需要注意的是,由于一个进程在同一时间只进行一个任务,所以子进程调用完之后,必须调用join()方法,使其父进程等待,否则进程将会成为僵尸进程。而对于线程来说,并不是必要join()。
进程之间也可以共享内存,但是在设计上,进程应该是资源拥有的基本单位,所以应该尽量避免进程之间共享内存,由于同步的需求,这样会降低程序的效率。
通过锁(Lock)来实现进程之间的同步:Lock实例有两个主要的方法:acquire()、released(),一把锁只能被一个进程占用。
进程之间可以通过Pipe和Queue通信,
其中Pipe实例时,默认是双向通道,管道的任何一端都可以收发消息,实例化时通过指定duplex=False即可创建单向通道,实例之后会得到包含两个元素的元组,代表管道的两端:
from multiprocessing import Pipe,Process
def proc1(pipe):
pipe.send('There is proc1')
print('proc1 recv:',pipe.recv())
def proc2(pipe):
pipe.send('There is proc2')
print('proc2 recv:',pipe.recv())
def main():
pipe = Pipe()
p1 = Process(target=proc1,args=(pipe[0],))
p2 = Process(target=proc2,args=(pipe[1],))
p1.start()
p2.start()
p1.join()
p2.join()
而Queue则是一个队列,满足先进先出原则(Pipe也是先进先出结构,如果发送多条信息,则会按照先进先出的顺序接收),并且Queue支持多个进程同时传入消息,并且支持多个进程同时读取消息,在实例化时,指定一个整数来限制最大允许的进程数:
from multiprocessing import Queue,Process
import os
def inQueue(queue):
info = 'put from proc:%s'%os.getpid()
queue.put(info)
def outQueue(queue):
info = queue.get()
print('%s get a info of %s'%(os.getpid(),info))
def main():
queue = Queue(5)
processes1 = []
processes2 = []
for i in range(10):
process = Process(target = inQueue,args=(queue,))
process.start()
processes1.append(process)
for i in range(10):
process = Process(target = outQueue,args=(queue,))
process.start()
processes2.append(process)
for proc in processes1:
proc.join()
queue.close()
for proc in processes2:
proc.join()
虽然在Queue中遵循先进先出的原则,但是由于上述代码并没有做进程同步,如果要如实反应Queue中的情况,应该添加锁:
from multiprocessing import Process,Queue,Lock
import os
def inQueue(queue,lock):
lock.acquire()
info = 'put from proc:%s'%os.getpid()
print '%s put a info'%os.getpid()
queue.put(info)
lock.release()
def outQueue(queue,lock):
lock.acquire()
info = queue.get()
print('%s get a info of %s'%(os.getpid(),info))
lock.release()
def main1():
queue = Queue(10)
lock = Lock()
processes1 = []
processes2 = []
for i in range(10):
process = Process(target = inQueue,args=(queue,lock))
process.start()
processes1.append(process)
for i in range(10):
process = Process(target = outQueue,args=(queue,lock))
process.start()
processes2.append(process)
for proc in processes1:
proc.join()
queue.close()
for proc in processes2:
proc.join()
多线程
多线程即一个进程中执行的任务的多个子任务,从设计上应该是独立调度和分配的基本单元。Python中多线程使用threading模块实现。
threading和multiprocessing类似,具有一个Thread类,用来实例化线程对象,Thread实例和Process一样也具有start(),join()等方法。
前面提到进程中最好不要有资源的交换,所以锁模型在进程中比较少用到,而在线程中就比较普遍,线程与锁模型是基本的并发模型,线程中的Lock和进程中一样,也具有acquire()方法和release()方法。
然而,在python中,多线程并发并不能完美地执行,这是因为Python的官方解释器CPython在设计时,添加了GIL锁,任何Python线程执行之前都必须获得GIL锁,每执行100条字节码GIL锁会得到释放,所以Python中的多线程仍然是交替进行的,Python中多线程只能用到同一个CPU,如果要使用多个CPU,需要用到多进程来完成。
但是这并不表示python中的多线程没有意义,虽然不能运用多核硬件,但是同一个任务多线程执行会比开多个进程效率要高很多。
Python并发实践_01_线程与进程初探的更多相关文章
- 《转载》Python并发编程之线程池/进程池--concurrent.futures模块
本文转载自Python并发编程之线程池/进程池--concurrent.futures模块 一.关于concurrent.futures模块 Python标准库为我们提供了threading和mult ...
- Python并发编程之线程池&进程池
引用 Python标准库为我们提供了threading和multiprocessing模块编写相应的多线程/多进程代码,但是当项目达到一定的规模,频繁创建/销毁进程或者线程是非常消耗资源的,这个时候我 ...
- Python并发编程之线程池/进程池--concurrent.futures模块
一.关于concurrent.futures模块 Python标准库为我们提供了threading和multiprocessing模块编写相应的多线程/多进程代码,但是当项目达到一定的规模,频繁创建/ ...
- python网络编程基础(线程与进程、并行与并发、同步与异步、阻塞与非阻塞、CPU密集型与IO密集型)
python网络编程基础(线程与进程.并行与并发.同步与异步.阻塞与非阻塞.CPU密集型与IO密集型) 目录 线程与进程 并行与并发 同步与异步 阻塞与非阻塞 CPU密集型与IO密集型 线程与进程 进 ...
- python并发编程之线程/协程
python并发编程之线程/协程 part 4: 异步阻塞例子与生产者消费者模型 同步阻塞 调用函数必须等待结果\cpu没工作input sleep recv accept connect get 同 ...
- Python并发编程03 /僵孤进程,孤儿进程、进程互斥锁,进程队列、进程之间的通信
Python并发编程03 /僵孤进程,孤儿进程.进程互斥锁,进程队列.进程之间的通信 目录 Python并发编程03 /僵孤进程,孤儿进程.进程互斥锁,进程队列.进程之间的通信 1. 僵尸进程/孤儿进 ...
- python并发编程02 /多进程、进程的创建、进程PID、join方法、进程对象属性、守护进程
python并发编程02 /多进程.进程的创建.进程PID.join方法.进程对象属性.守护进程 目录 python并发编程02 /多进程.进程的创建.进程PID.join方法.进程对象属性.守护进程 ...
- Python网络编程之线程,进程
一. 线程: 基本使用 线程锁 线程池 队列(生产者消费者模型) 二. 进程: 基本使用 进程锁 进程池 进程数据共享 三. 协程: gevent greenlet 四. 缓存: memcache ...
- python学习笔记12 ----线程、进程
进程和线程的概念 进程和线程是操作系统中两个很重要的概念,对于一般的程序,可能有若干个进程,每一个进程有若干个同时执行的线程.进程是资源管理的最小单位,线程是程序执行的最小单位(线程可共享同一进程里的 ...
随机推荐
- FastDFS迁移步骤
1.在新的机器上安装FastDFS 2.将新的storage接到老的tracker机器上,用来同步数据(/usr/local/fastdfs/bin/fdfs_storaged) 数据同步完成后,需要 ...
- 大数据学习系列之三 ----- HBase Java Api 图文详解
版权声明: 作者:虚无境 博客园出处:http://www.cnblogs.com/xuwujing CSDN出处:http://blog.csdn.net/qazwsxpcm 个人博客出处:http ...
- python3 三级菜单-基础版
# -*- coding:utf-8 -*- data = { "北京":{ "东城区":{ "安定门":["国子监", ...
- java web学习笔记 servlet
关于java web web.xml中一般配置的都是与servlet先关的可以配置servlet filter listener context-param用来配置web应用的启动参数,可用通过Ser ...
- cocos2d-x3.6 连连看完整源代码
我的博客:http://blog.csdn.net/dawn_moon 好了,这个连连看是用最新版cocos2d-x 3.6版写的,里面使用了非常多新特性. 基本完工了.另一个积分和关卡没有做.有兴趣 ...
- EBS採购模块中的级联接收和级联接收事务
EBS採购模块中的级联接收和级联接收事务 (版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习.请注明出处:否则请与本人联系.违者必究) 级联接收和级联接收事务 级联功能对来自于同一个供应商 ...
- Spring基础知识之基于注解的AOP
背景概念: 1)横切关注点:散布在应用中多处的功能称为横切关注点 2)通知(Advice):切面完成的工作.通知定了了切面是什么及何时调用. 5中可以应用的通知: 前置通知(Before):在目标方法 ...
- Python爬虫(二十四)_selenium案例:执行javascript脚本
本章叫介绍如何使用selenium在浏览器中使用js脚本,更多内容请参考:Python学习指南 隐藏百度图片 #-*- coding:utf-8 -*- #本篇将模拟执行javascript语句 fr ...
- 使用Mybatis进行多表联查操作
(1)增加一个测试数据库shop_order,sql语句如下: CREATE DATABASE `shop_order`; USE `shop_order`; CREATE TABLE `t_user ...
- C# Lock、Monitor避免死锁
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...