python-多线程等概念
并发 & 并行
并发:是指系统具有处理多个任务的能力
并行:是指系统具有 同时 处理多个任务的能力
并行 是 并发的一个子集
同步 & 异步
同步:当进程执行到一个I/O(等待外部数据的时候)----------等 : 同步
异步: ----------不等,直到接收到数据再回来执行
GIL:全局解释锁
因为有GIL锁,所以同一时刻,只有一个线程被CPU执行
任务:IO密集型
计算密集型
对于IO密集型:Python 的多线程是有意义的
可以采用多进程+协程
对于计算密集型:Python 的多线程就不推荐了,不适用了。
线程锁(互斥锁Mutex)
一个进程下可以启动多个线程,多个线程共享父进程的内存空间,也就意味着每个线程可以访问同一份数据,此时,如果2个线程同时要修改同一份数据,会出现什么状况?
import
time
import
threading
def
addNum():
global
num
#在每个线程中都获取这个全局变量
print
(
'--get num:'
,num )
time.sleep(
1
)
lock.acquire()
#修改数据前加锁
num
-
=
1
#对此公共变量进行-1操作
lock.release()
#修改后释放
num
=
100
#设定一个共享变量
thread_list
=
[]
lock
=
threading.Lock()
#生成全局锁
for
i
in
range
(
100
):
t
=
threading.Thread(target
=
addNum)
t.start()
thread_list.append(t)
for
t
in
thread_list:
#等待所有线程执行完毕
t.join()
print
(
'final num:'
, num )
RLock(递归锁)
说白了就是在一个大锁中还要再包含子锁
import threading,time def run1():
print("grab the first part data")
lock.acquire()
global num
num +=
lock.release()
return num
def run2():
print("grab the second part data")
lock.acquire()
global num2
num2+=
lock.release()
return num2
def run3():
lock.acquire()
res = run1()
print('--------between run1 and run2-----')
res2 = run2()
lock.release()
print(res,res2) if __name__ == '__main__': num,num2 = ,
lock = threading.RLock()
for i in range():
t = threading.Thread(target=run3)
t.start() while threading.active_count() != :
print(threading.active_count())
else:
print('----all threads done---')
print(num,num2)
Semaphore(信号量)
互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去。
import threading,time def run(n):
semaphore.acquire()
time.sleep()
print("run the thread: %s\n" %n)
semaphore.release() if __name__ == '__main__': num=
semaphore = threading.BoundedSemaphore() #最多允许5个线程同时运行
for i in range():
t = threading.Thread(target=run,args=(i,))
t.start() while threading.active_count() != :
pass #print threading.active_count()
else:
print('----all threads done---')
print(num)
Event
通过Event来实现两个或多个线程间的交互,下面是一个红绿灯的例子,即起动一个线程做交通指挥灯,生成几个线程做车辆,车辆行驶按红灯停,绿灯行的规则。
import threading,time
import random
def light():
if not event.isSet():
event.set() #wait就不阻塞 #绿灯状态
count =
while True:
if count < :
print('\033[42;1m--green light on---\033[0m')
elif count <:
print('\033[43;1m--yellow light on---\033[0m')
elif count <:
if event.isSet():
event.clear()
print('\033[41;1m--red light on---\033[0m')
else:
count =
event.set() #打开绿灯
time.sleep()
count +=
def car(n):
while :
time.sleep(random.randrange())
if event.isSet(): #绿灯
print("car [%s] is running.." % n)
else:
print("car [%s] is waiting for the red light.." %n)
if __name__ == '__main__':
event = threading.Event()
Light = threading.Thread(target=light)
Light.start()
for i in range():
t = threading.Thread(target=car,args=(i,))
t.start()
队列queue (重点)
1,queue.Queue() FIFO队列-先进先出
2,queue.LifoQueue() LIFO队列,先进后出
3,queue.PriorityQueue() 按照优先级,越低越先出
方法:
q.size 返回队列大小
q.empty() 如果队列为空返回true
q.full() 如果队列为满返回true
q.get () 里面可以设置block 的t,f
q.put()
q.join()实际是队列为空时再执行别的操作
生产者消费者模型
在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。
为什么要使用生产者和消费者模式
在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。
什么是生产者消费者模式
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
import threading
import queue def producer():
for i in range():
q.put("骨头 %s" % i ) print("开始等待所有的骨头被取走...")
q.join()
print("所有的骨头被取完了...") def consumer(n): while q.qsize() >: print("%s 取到" %n , q.get())
q.task_done() #告知这个任务执行完了 q = queue.Queue() p = threading.Thread(target=producer,)
p.start() c1 = consumer("李闯")
import time,random
import queue,threading
q = queue.Queue()
def Producer(name):
count =
while count <:
time.sleep(random.randrange())
q.put(count)
print('Producer %s has produced %s baozi..' %(name, count))
count +=
def Consumer(name):
count =
while count <:
time.sleep(random.randrange())
if not q.empty():
data = q.get()
print(data)
print('\033[32;1mConsumer %s has eat %s baozi...\033[0m' %(name, data))
else:
print("-----no baozi anymore----")
count +=
p1 = threading.Thread(target=Producer, args=('A',))
c1 = threading.Thread(target=Consumer, args=('B',))
p1.start()
c1.start()
多进程multiprocessing
from multiprocessing import Process
import os def info(title):
print(title)
print('module name:', __name__)
print('parent process:', os.getppid())
print('process id:', os.getpid())
print("\n\n") def f(name):
info('\033[31;1mfunction f\033[0m')
print('hello', name) if __name__ == '__main__':
info('\033[32;1mmain process line\033[0m')
p = Process(target=f, args=('bob',))
p.start()
p.join()
进程间通讯
不同进程间内存是不共享的,要想实现两个进程间的数据交换,可以用以下方法:
Queues
使用方法跟threading里的queue差不多
from multiprocessing import Process, Queue def f(q):
q.put([, None, 'hello']) if __name__ == '__main__':
q = Queue()
p = Process(target=f, args=(q,))
p.start()
print(q.get()) # prints "[42, None, 'hello']"
p.join()
from multiprocessing import Process, Pipe def f(conn):
conn.send([, None, 'hello'])
conn.close() if __name__ == '__main__':
parent_conn, child_conn = Pipe()
p = Process(target=f, args=(child_conn,))
p.start()
print(parent_conn.recv()) # prints "[42, None, 'hello']"
p.join()
Managers
Manager返回的Manager对象()控制一个承载Python对象的服务器进程,并允许其他进程使用代理来操纵它们。
经理返回的经理()将支持类型 list
, dict
, Namespace
, Lock
, RLock
, Semaphore
, BoundedSemaphore
, Condition
, Event
, Barrier
, Queue
, Value
and Array
from multiprocessing import Process, Manager def f(d, l):
d[] = ''
d[''] =
d[0.25] = None
l.append()
print(l) if __name__ == '__main__':
with Manager() as manager:
d = manager.dict() l = manager.list(range())
p_list = []
for i in range():
p = Process(target=f, args=(d, l))
p.start()
p_list.append(p)
for res in p_list:
res.join() print(d)
print(l)
进程池
进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。
进程池中有两个方法:
- apply
- apply_async
from multiprocessing import Process,Pool
import time def Foo(i):
time.sleep()
return i+ def Bar(arg):
print('-->exec done:',arg) pool = Pool() for i in range():
pool.apply_async(func=Foo, args=(i,),callback=Bar)
#pool.apply(func=Foo, args=(i,)) print('end')
pool.close()
pool.join()#进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。
python-多线程等概念的更多相关文章
- Python多线程锁
[Python之旅]第六篇(四):Python多线程锁 python lock 多线程 多线程使用方法 多线程锁 摘要: 在多线程程序执行过程中,为什么需要给一些线程加锁以及如何加锁,下面就来 ...
- Day9 - Python 多线程、进程
Python之路,Day9, 进程.线程.协程篇 本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线 ...
- 搞定python多线程和多进程
1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发 ...
- 进程,线程,GIL,Python多线程,生产者消费者模型都是什么鬼
1. 操作系统基本知识,进程,线程 CPU是计算机的核心,承担了所有的计算任务: 操作系统是计算机的管理者,它负责任务的调度.资源的分配和管理,统领整个计算机硬件:那么操作系统是如何进行任务调度的呢? ...
- python多线程、多进程以及GIL
多线程 使用threading模块创建线程 传入一个函数 这种方式是最基本的,即调用threading中的Thread类的构造函数,然后指定参数target=func,再使用返回的Thread的实例调 ...
- 浅析Python多线程
学习Python多线程的资料很多,吐槽Python多线程的博客也不少.本文主要介绍Python多线程实际应用,且假设读者已经了解多线程的基本概念.如果读者对进程线程概念不甚了解,可参见知名博主 阮一峰 ...
- day-3 python多线程编程知识点汇总
python语言以容易入门,适合应用开发,编程简洁,第三方库多等等诸多优点,并吸引广大编程爱好者.但是也存在一个被熟知的性能瓶颈:python解释器引入GIL锁以后,多CPU场景下,也不再是并行方式运 ...
- Python多线程操作
多线程是一门编程语言的重要操作. GIL(全局解释器锁)存在于python解释器中,用来确保当前只有一个线程被执行,当一个线程获得GIL后,这个线程将被执行,退出时释放GIL,由下一个获得GIL的线程 ...
- python多线程和多进程
1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发 ...
- Python 多线程和线程池
一,前言 进程:是程序,资源集合,进程控制块组成,是最小的资源单位 特点:就对Python而言,可以实现真正的并行效果 缺点:进程切换很容易消耗cpu资源,进程之间的通信相对线程来说比较麻烦 线程:是 ...
随机推荐
- css table样式
1.table样式首先设置表格边框,属性设置表格的边框是否被合并为一个单一的边框. table{ border-collapse: collapse; border-spacing: 0;} 2.固定 ...
- Atitit php vs node.js attilax总结
Atitit php vs node.js attilax总结 1.1. 上手度 还是php 1 1.2. Node.js最大的缺点 异步回调导致可读性差..特别嵌套的时候.. 1 1.1. 上手 ...
- [docker]docker自带的overlay网络实战
overlay网络实战 n3启动consul docker run -d -p 8500:8500 -h consul --name consul progrium/consul -server -b ...
- zookeeper的可视化web界面
转载一篇我心中大神有关zookeeper WEB的文章 以前写过一篇zookeeper集群搭建的文章<烂泥:zookeeper集群搭建>,最近在使用activemq集群过程中碰到了一些有 ...
- ES Grafana
https://github.com/trevorndodds/elasticsearch-metrics https://grafana.com/dashboards/878 https://gra ...
- 安装oracle遇到的故障
安装oracle遇到的故障 安装oracle遇到的故障总结 os:centos4.7(64位)db版本:oracle10.0.2.1(64位) 这次安装oracle又遇到点小问题,每次都是遇到点小问题 ...
- 树莓派2上手 —— Raspbian的一些基本配置问题
先说点废话: 原来的笔记本因为上次被儿子拿着充电器玩的时候漏电烧了主板,修了之后还是时不时就突然宕机,Windows也完全起不来.后面这个问题倒是不大,真要用Windows的时候拿老婆的用一下就是了, ...
- WebMisCentral-Client 适配MySql数据库
由于本身WebMisCentral采用的是EF5.0,所以适配起来还是非常简单的,下面看操作: 1.ElegantWM.WebUI层中(或者ElegantWM.DAL)通过NUGET下载MySQL.D ...
- SASS常用语法
原文地址:这里 @charset "UTF-8"; /** * 自定义变量 */ $blue: #1875e7; div { color: $blue; } /** * 变量要嵌在 ...
- 【转】 Windows下配置Git
[转自]http://blog.csdn.net/exlsunshine/article/details/18939329 1.从git官网下载windows版本的git:http://git-scm ...