python 并发编程

来源:互联网 发布:查看淘宝客佣金 编辑:程序博客网 时间:2024/06/06 01:33

概念

首先我们先了解下关于 并发与并行 的概念,这很容易让人混淆如果不注意的话,甚至会有人认为两者是一样的,统称为大家熟悉的并发编程;
引用下Erlang之父的解释:
Concurrent
Two queues and one coffee machine.
Parallel
Two queues and two coffee machines.
个人理解:
并发:可以理解为多个线程在单核上交替运行,每个线程都会分得一定的CPU时间片;
并行:可以理解为多个线程在多核上同时运行,每个线程都会独享一个CPU;

进程、线程、协程的区别:

  • 进程:
在Python中可以理解为仅只有进程可以称为并发编程,可以充分利用多核,它不像Java和C++,因为会受制于Python的GIL(Global Interpreter Lock)全局解释器锁。
  • 线程:
        Python的多线程在某种程度上讲是比较尴尬的存在,受制于Python的GIL(Global Interpreter Lock)全局解释器锁,阻止Python代码同时在多个处理器核心上运行,因为一个Python解释器在同一时刻只能运行于一个处理器之中。
        1、对于CPU密集型计算, 并不能算真正的并行计算,不能发挥多核的作用;
        2、对于IO 密集型(如爬虫等),由于GIL的原因,虽然在性能上优于单线程,但多线程的切换, 资源的申请释放 成本开销同样也是不可忽略的。
  • 协程:
        在线程与协程之间,个人更偏向于协程,
        1、线程资源开销远大于协程, 线程它有自己的线程空间,在linux下可以理解为一个轻量级进程;
        2、线程的上下文切换可能会引起寄存器和内存间的复制拷贝等;协程在进行切换时,是代码块进行切换(栈跳转),可以更多的利用CPU时间片;


编程样例:

多进程使用

# -*- encoding:utf8 -*-"""    author: quanbin_zhu    time  : 2017/9/8 18:41"""import multiprocessing#方法一:将要执行的方法作为参数传给Thread的构造方法def work(id):    time.sleep(1)    print 'the process id is:%s' % idfor i in xrange(3):    p = multiprocessing.Process(target=work, args=(i,))    p.start()#方法二:从Process继承,并重写run()class WorkProcess(multiprocessing.Process):    def __init__(self, id):        multiprocessing.Process.__init__(self)        self.id = id    def run(self):        print 'the process id is:%s' % self.idfor i in xrange(3):    p = WorkProcess(i)    p.start()


多线程使用

# -*- encoding:utf8 -*-"""    author: quanbin_zhu    time  : 2017/9/8 18:46"""import threadingimport time#方法一:将要执行的方法作为参数传给Thread的构造方法def show(id):    time.sleep(1)    print 'the thread id is:%s' % idfor i in xrange(3):    t =threading.Thread(target=show,args=(i,))    t.start()#方法二:从Thread继承,并重写run()class MyThread(threading.Thread):    def __init__(self, id):        super(MyThread, self).__init__()        self.id = id    def run(self):        time.sleep(1)        print 'the thread id is:%s' % self.idfor i in xrange(3):    t =MyThread(i)    t.start()


多协程使用

# -*- encoding:utf8 -*-"""    author: quanbin_zhu    time  : 2017/9/8 18:51"""import geventfrom gevent import monkey;monkey.patch_all()from gevent.pool import Poolfrom functools import partialclass Task(gevent.Greenlet):    def __init__(self, id):        super(Task, self).__init__()        self.task_id = id    def _run(self):        for index in xrange(1, 6):            print "task id %s,  output value %s" % (self.task_id, index)            gevent.sleep(0)def show(id, f, t):    for index in xrange(f, t):        print "task id %s,  output value %s" % (id, index)        gevent.sleep(0)# 方法调用def func_dispatch():    func = partial(show, f = 1, t=3)    g1 = gevent.spawn(func, "gevent-01")    g1.join()# 类调用def class_dispatch():    tasks = [ Task(i) for i in xrange(0,3)]    map(lambda t: t.start(), tasks)    map(lambda t: t.join(), tasks)# 类和Pool结合调用def class_dispatch_with_pool():    tasks = [Task(i) for i in xrange(0, 3)]    pools = Pool(2)    map(lambda t: pools.start(t), tasks)    pools.join()if __name__ == '__main__':    func_dispatch()


原创粉丝点击