美文网首页Python实例教程
Python的 并发、并行

Python的 并发、并行

作者: 欢喜明 | 来源:发表于2018-05-06 18:20 被阅读0次

记录:

并发:在一个时间段,处理多个任务,单核也可以并发(CPU分时间片);

并行:在同一个时刻,处理多个任务,必须多核才能并行;

一、Python实现并发的手段:

1、操作系统提供:进程、线程;

2、编程语言提供:协程:用户空间的调度(py3);

题外话:

现在的操作系统,进程和线程的区别越来越小,因为进程越来越轻了;实际上,Linux的线程是通过进程实现的;

二、Python的进程和线程的区别:

Python每个进程都会启动一个解释器;

Python每个线程(一个进程下面的)共享一个解释器;

ps:Python没有提供主动停止线程的方法的;只能等线程处理完毕,或者主线程结束;所以在线程逻辑里面一定要写退出逻辑;

三、logging库:

通常用logging代替print,因为logging是线程安全的,在多线程下,输出表现正常,而print是非线程安全的,在多线程下,输出表现会出现异常,例如,T1没输出完毕,T2又进行输出了;

四、Python 线程的 daemon 属性:

默认是false;

daemon:守护、守护进程;

守护进程:Daemon()程序是一直运行的服务端程序,又称为守护进程。通常在系统后台运行,没有控制终端,不与前台交互,Daemon程序一般作为系统服务使用。Daemon是长时间运行的进程,通常在系统启动后就运行,在系统关闭时才结束。

知识点一:

当一个进程启动之后,会默认产生一个主线程,因为线程是程序执行流的最小单元,当设置多线程时,主线程会创建多个子线程,在python中,默认情况下(其实就是setDaemon(False)),主线程执行完自己的任务以后,就退出了,此时子线程会继续执行自己的任务,直到自己的任务结束;

知识点二:

当我们使用setDaemon(True)方法,设置子线程为守护线程时,主线程一旦执行结束,则全部线程全部被终止执行,可能出现的情况就是,子线程的任务还没有完全执行结束,就被迫停止;

知识点三:

join所完成的工作就是线程同步,即主线程任务结束之后,进入阻塞(等待)状态,一直等待其他的子线程执行结束之后,主线程在终止;

知识点四:

join有一个timeout参数:

当设置守护线程时,含义是主线程对于子线程等待timeout的时间将会杀死该子线程,最后退出程序。所以说,如果有10个子线程,全部的等待时间就是每个timeout的累加和。简单的来说,就是给每个子线程一个timeout的时间,让他去执行,时间一到,不管任务有没有完成,直接杀死。

没有设置守护线程时,主线程将会等待timeout的累加和这样的一段时间,时间一到,主线程结束,但是并没有杀死子线程,子线程依然可以继续执行,直到子线程全部结束,程序退出。

t1.join(),子线程设置这个就是让主线程阻塞(等待),那么在哪里设置了 t1.join(),主线程就在这里等待t1执行完毕,再继续往下执行;因为两个线程顺序完成,看起来象一个线程,所以称为线程的合并,其实也是让线程同步了;

注意(看到的结果是这样,解释可能不太正确):

(1)看图:

t1设置执行2秒;t2设置执行3秒;目的是为了t1先于t2执行完毕;

t1没有设置daemon线程,所以当主线程结束后,t1仍然会继续执行完毕,所以查看结果:当输出 main end ... 后,仍然有 t1 out ... 输出;

t2设置为daemon线程,所以当主线程结束后,t2也被主线程杀死了(t1已结执行完毕),跟着结束了,程序(进程)也结束了,所以没有 t2 out... 输出;

注意,这里一定要保证t1(非daemon子线程)先于t2执行完毕;因为如果t1要比t2耗时长的话,因为 t1是非daemon子线程,即是主线程结束了,t1仍然要继续执行的,所以整个程序(进程)并不会结束,也就没有杀死t2,导致t2也会执行完毕;看下面:

可以看到:即是t2是daemon子线程,但是仍然执行完毕了,并没有因为主线程的退出而被杀死,因为t1的执行时间比t2长;

ps:如果不是以继承的方式创建线程,那么run方法和start方法只能执行其中一个;通常也不建议使用继承的方式;start方法是子线程执行的,启动子线程;

要注意:主线程、父线程、子线程的关系;

五、Python中的ThreadLocal变量

注意,并不是子线程要执行的目标函数里面的局部变量,虽然每个线程即使是执行同一个函数,都会有自己的内存的,互不干扰,但是函数里面的局部变量,就是属于函数的,到了另外一个函数不会认识此局部变量;

而Python的threadlocal变量,是属于线程的,此线程调用的所有函数都认识threadlocal变量,eg.:

global_data = threading.local()

def show():

        print (threading.current_thread().getName(), global_data.num

def thread_cal():

        global_data.num = 0

        for _ in xrange(1000):

            global_data.num += 1

        show()

每个线程都可以通过 global_data.num 获得自己独有的数据,并且每个线程读取到的 global_data 都不同,真正做到线程之间的隔离。其他线程是不认识global_data.num的;

六、线程同步方式(前三个方式需要在具体了解)

线程的同步,有一层意思就是:线程之间的通讯,线程总是有某种关联,才需要同步的,而同步就意味着阻塞(等待);

1、event

两个线程之间事件的通知,我发现了一个事件,set,你就可以查看。

2、lock (rlock?)

保护共享资源;

3、condition

生产者消费者模式;生产者唤醒消费者;

4、Barrier(栅栏)

就是线程们在等待,直到线程数满足设定的数量之和,才继续执行;

可以使用此方法开发并发测试工具;

一些关键语句:

barrier = threading.Barrier(3)  #等齐3个线程

worker_id = barrier.wait()  #线程执行到这一句,就等着,满足数量之后,再往下走

barrier.n_waiting  #现在在等待的线程数量

barrier.abort()  #通知已经在等待的线程,不必再等了,我执行不到wait()了(任何一个线程执行都可以),当abort()方法被执行,wait()方法就会抛出异常

5、semaphore (信号量)

s = threading.Semaphore(2)

s.acquire() # 获得,在线程中,也是锁住某个变量,自己此刻独占;

输出:True  # 成功锁住

s.acquire(False) # 再来一次

输出:True  # 成功锁住

s.acquire(False) # 再来一次

输出:False # 没有锁

锁是信号量的特例:为1的信号量;

信号量也是对共享资源的保护,但是和锁不一样,锁限制只有一个线程可以访问共享资源,而信号量限制指定个线程可以访问共享资源;所以信号量可以用于做连接池的功能;

七、异步编程

1、概念

同步、异步:

发生在函数调用的时候,是否得到直接最终结果;

得到直接最终结果的是:同步调用;

不得到直接最终结果的是:异步调用;

阻塞、非阻塞:

发生在函数调用的时候,是否立刻返回;

立刻返回:非阻塞调用;

不立刻返回:阻塞调用;

ps:同步、异步 与 阻塞、非阻塞 在概念上是不相关的;

同步、异步:关注的是结果;

阻塞、非阻塞:关注的是是否等待;

ps:异步非阻塞是最好的性能咯;

同步IO、异步IO、IO多路复用:

相关文章

  • Python

    python的并行、并发: 并发:在一个时间段,处理多个任务,单核也可以并发(CPU分时间片); 并行:在同一个时...

  • Python的 并发、并行

    记录: 并发:在一个时间段,处理多个任务,单核也可以并发(CPU分时间片); 并行:在同一个时刻,处理多个任务,必...

  • Python并行编程(一):线程的基本概念和线程的两种定义方法以

    前言:本系列将包含Python并行编程的相关技术内容,包括Python线程、Python进程、并发编程的异步模式及...

  • 索引 - Python

    文集主页 Python 解释器和三种栈多进程、多线程、协程、并发并行Python I/O 操作(一)Python ...

  • 服务器并发设计

    并发与并行 并发技术选型 结构并发 状态并发 集群和负载均衡 并发(Coccurrency)和并行(Paralle...

  • 30 多任务

    并发和并行 并发:多个事件在同一时间段内发生 并行:多个事件在同一时刻发生 这个Python那里有讲过,具体不再复...

  • JS异步编程相关知识点

    并发(concurrency)和并行(parallelism)区别 涉及面试题:并发与并行的区别? 并发是宏观概念...

  • Python(2)---并发编程

    目录 1. Python多线程与多进程知识1.1 并发与并行1.2 线程(thread)与进程(process)...

  • Golang学习笔记-Goroutines

    并发 首先 go 是一个实现并发的语言,并非并行 并发 vs 并行 并行是在同一时间内,可以同时执行多个任务;并发...

  • Python多进程(Multiprocessing)的简单使用

    Python由于GIL的存在,多线程(Thread)、协程(Asyncio)可以实现并发,并行则依赖多进程(Mul...

网友评论

    本文标题:Python的 并发、并行

    本文链接:https://www.haomeiwen.com/subject/uzrurftx.html