python并发编程之协程

时间:2022-09-02 08:42:59

---恢复内容开始---

一、join方法

(1)开一个主线程

from threading import Thread,currentThread
import time
def walk():
print('%s is running'%currentThread().getName())
time.sleep(2)
print('%s is done'%currentThread().getName())
if __name__ == '__main__':
# for i in range(10):
p=Thread(target=walk)
p.start()
p.join()
print('主') #主线程在等p.join执行

开一个主线程

(2)开多个主线程,并发运行

from threading import Thread,currentThread
import time
def walk():
print('%s is running'%currentThread().getName())
time.sleep(2)
print('%s is done'%currentThread().getName())
if __name__ == '__main__':
l=[]
for i in range(10):
p=Thread(target=walk)
l.append(p)
p.start()
# p.join() #在p.start() 跟p.join()就会变为串行,一个一个的运行
for p in l:
p.join()
print('主')

开多个主线程

(3)并发运行 互斥锁之锁局部的 ,用所只锁住你对共享数据修改的部分

加锁:

from threading import Thread,currentThread,Lock
import time
n=100
def walk():
# 并发运行
time.sleep(2)
global n
mutex.acquire()
# 串行
temp=n
time.sleep(0.01)
n=temp-1 #数据可能同是减1,可能数据会乱
mutex.release()
if __name__ == '__main__':
mutex=Lock()
l=[]
start = time.time()
for i in range(100):
p=Thread(target=walk)
l.append(p)
p.start()
for p in l:
p.join()
stop = time.time()
print('n:%s run_time : %s' %(n,stop - start))

不加锁:

from threading import Thread,currentThread,Lock
import time
n=100
def walk():
time.sleep(2)
global n
# mutex.acquire()
temp=n
time.sleep(0.1)
n=temp-1 #数据可能同是减1,可能数据会乱
# mutex.release()
if __name__ == '__main__':
mutex=Lock()
start = time.time()
for i in range(10):
p=Thread(target=walk)
p.start()
p.join()
stop = time.time()
print('n:%s run_time : %s' %(n,stop - start)) #至少21秒

并发运行,不加锁

主线程运行完毕是在所有线程所在的进程内所有非守护线程运行完毕才运行

二、GIL本质是一把互斥锁,将并发转成串行,以此来控制同一时间内共享数据只能被一个任务修改,

     进而保证数据的安全

from threading import Thread,currentThread,Lock
import time
n=100
def work():
time.sleep(2)
global n
time.sleep(0.5)
mutex.acquire()
temp=n
time.sleep(0.1)
n=temp-1
mutex.release()
if __name__ == '__main__':
mutex=Lock()
t1=Thread(target=work)
t2=Thread(target=work)
t3=Thread(target=work)
t1.start()
t2.start()
t3.start()

python并发编程之协程

三、多线程性能测试

(1)'''
多进程
优点:可以利用多核
缺点:开销大 多线程
优点:开销小
缺点:不可以利用多核
'''
from multiprocessing import Process
from threading import Thread
import time
def work():
res=0
for i in range(10000000):
res+=i if __name__ == '__main__':
l=[]
start=time.time()
for i in range(4):
# p=Process(target=work) #0.9260530471801758
p=Thread(target=work) #0.9260530471801758
l.append(p)
p.start() for p in l:
p.join() stop=time.time()
print('%s' %(stop-start))

计算机密集型--开启多进程

from multiprocessing import Process
from threading import Thread
import time
def work():
time.sleep(2) if __name__ == '__main__':
l=[]
start=time.time()
for i in range(400):
p=Process(target=work)
# p=Thread(target=work)
l.append(p)
p.start() for p in l:
p.join() stop=time.time()
print('%s' %(stop-start))

I/O密集型---开启多线程

(2)应用:

             多线程用于IO密集型,如socket,爬虫,web
            多进程用于计算密集型,如金融分析

四、死锁与递归锁

死锁:

from threading import Thread,RLock
import time
mutexA=RLock()
class MyThread(Thread):
def run(self):
self.f1()
self.f2()
def f1(self):
mutexA.acquire()
print('%s 拿到A锁'%self.name)
mutexA.acquire()
print('%s 拿到B锁' % self.name)
mutexA.release()
mutexA.release()
def f2(self):
mutexA.acquire()
print('%s 拿到A锁' % self.name)
time.sleep(1)
mutexA.acquire()
print('%s 拿到B锁' % self.name)
mutexA.release()
mutexA.release()
if __name__ == '__main__':
for i in range(10):
t=MyThread()
t.start()

解决死锁的方法

递归锁:用RLock代替Lock

 from threading import Lock,Thread,RLock
import time
# mutexA=Lock()
# mutexB=Lock()
mutexB=mutexA=RLock()
class MyThread(Thread):
def run(self):
self.f1()
self.f2()
def f1(self):
mutexA.acquire()
print('\033[32m%s 拿到A锁' %self.name)
mutexB.acquire()
print('\033[45m%s 拿到B锁' %self.name)
mutexB.release()
mutexA.release()
def f2(self):
mutexB.acquire()
print('\033[32m%s 拿到B锁' %self.name)
time.sleep(1)
mutexA.acquire()
print('\033[45m%s 拿到A锁' %self.name)
mutexA.release()
mutexB.release()
if __name__ == '__main__':
for i in range(10):
t=MyThread()
t.start()

递归锁

五、信号量

信号量和进程一样

信号量就是一把锁,可以有多把钥匙

from threading import Thread,Semaphore,currentThread
import time,random
sm=Semaphore(5)
def task():
sm.acquire()
print('%s 上厕所' %currentThread().getName())
time.sleep(random.randint(1,3))
print('%s 走了' %currentThread().getName())
sm.release()
if __name__ == '__main__':
for i in range(20):
t=Thread(target=task)
t.start()

六、事件

Event

vent.isSet():返回event的状态值;
event.wait():如果 event.isSet()==False将阻塞线程;
event.set(): 设置event的状态值为True,所有阻塞池的线程激活进入就绪状态, 等待操作系统调度;
event.clear():恢复event的状态值为False。
from threading import Thread,currentThread,Event
import time
e=Event()
def traffic_ligths():
time.sleep(1)
e.set()
def car(): print('\033[45m%s等'%currentThread().getName())
e.wait()
print('\033[43m%s开'%currentThread().getName())
if __name__ == '__main__':
print('绿灯')
for i in range(10):
p=Thread(target=car)
p.start()
# print('绿灯')
time.sleep(5)
print('红灯')
traffic_ligth=Thread(target=traffic_ligths)
traffic_ligth.start()

红绿灯事列


from threading import Thread, currentThread, Event
import time
e = Event()
def conn_mysql():
count = 1
while not e.is_set():
if count > 3:
raise ConnectionError('尝试链接的次数太多了')
print('\033[45m%s 第%s次尝试' % (currentThread().getName(), count))
e.wait(timeout=1)
count += 1
print('\033[45m%s 开始链接' %currentThread().getName())
def check_myql():
print('\033[45m%s 开始检测 my_sql....' %currentThread().getName())
time.sleep(2)
e.set()
if __name__ == '__main__':
for i in range(2):
p = Thread(target=conn_mysql)
p.start()
p = Thread(target=check_myql)
p.start()

链接——sql

七、定时器

定时器,是n秒后执行操作

rom threading import Timer

def hello(n):
print("hello, world",n) t = Timer(3, hello,args=(123,))
t.start() # after 1 seconds, "hello, world" will be printed

定时器

八、线程queue

queue队列,用法与进程queue一样

q=queue.queue()  先进先出

q=queue.Queue(3) #先进先出
q.put('first')
q.put('second')
q.put('third')
# q.put('fourth') print(q.get())
print(q.get())
print(q.get())

q=queue.LifoQueue()   先进后出

q=queue.LifoQueue() #先进后出
q.put('first')
q.put('second')
q.put('third')
# q.put('fourth') print(q.get())
print(q.get())
print(q.get())
put进入一个元组,元组的第一个元素是优先级(通常是数字,也可以是非数字之间的比较),数字越小优先级越高
import queue
q=queue.PriorityQueue()
q.put((20,'a'))
q.put((10,'b'))
q.put((30,'c'))
print(q.get())
print(q.get())
print(q.get())

---恢复内容结束---

python并发编程之协程的更多相关文章

  1. python并发编程之协程知识点

    由线程遗留下的问题:GIL导致多个线程不能真正的并行,CPython中多个线程不能并行 单线程实现并发:切换+保存状态 第一种方法:使用yield,yield可以保存状态.yield的状态保存与操作系 ...

  2. 32 python 并发编程之协程

    一 引子 本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去 ...

  3. 四 python并发编程之协程

    一 引子 本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去 ...

  4. python并发编程之协程(实践篇)

    一.协程介绍 协程:是单线程下的并发,又称微线程,纤程.一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的. 对于单线程下,我们不可避免程序中出现io操作,但如果我们 ...

  5. 第十篇.5、python并发编程之协程

    一 引子 本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去 ...

  6. 第 12 章 python并发编程之协程

    一.引子 主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只用一个)情况下实现并发,并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去执行其他的任务(切换由操作 ...

  7. python 并发编程之协程

    一.协程 协程: 单线程下的并发,又称 微线程.协程是一种用户态的的轻量级线程,即协程是由用户程序自己控制调度的. ​ 协程的本质就是在单线程下,由用户自己控制一个任务,遇到 io 阻塞就切换另外一个 ...

  8. python全栈开发从入门到放弃之socket并发编程之协程

    一.为什么会有协程 本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情 ...

  9. 百万年薪python之路 -- 并发编程之 协程

    协程 一. 协程的引入 本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态 cpu正在运行一个任务,会在两 ...

随机推荐

  1. 【*】发现一个效果丰富酷炫的Android动画库

    没有什么比发现一个好*更让人开心的了. 这个库分分钟提高交互体验 :AndroidViewAnimations 一张图说明一切 配置和使用也相当简单 GitHub地址

  2. InterBase数据库迁移到MySQL(数据导出)

    这篇我将记叙我的第二个脚本程序,这篇我使用InterBase数据库提供的“isql”命令来导出我所要的数据,但是由于“isql”命令没有直接导出数据的语句,说以我采用的是导入一个配置文件,在这个文件中 ...

  3. java初学知识点

    public class EnumTest { public static void main(String[] args) { Size s=Size.SMALL; Size t=Size.LARG ...

  4. mac地址泛洪攻击的实验报告

    案例介绍: PC A 访问 本网络的一台FTPserver主机,中间人进行arp的投毒,获取PC-A和FTPserve之间的回话记录,截获用户名和密码. 实验拓扑:

  5. C语言第4天循环,流程控制。

    C语言第四天 :first-child { margin-top: 0; } blockquote > :last-child { margin-bottom: 0; } img { borde ...

  6. ulink 固件更新问题

    1前言 ulink版本升级.. 当使用keil4.7.4版本时,ulink固件库更新了. 2官方资料解释: Boot Mode Utility Home » Appendix » Utilities  ...

  7. 了解 C++ 默默编写并调用的函数

    前言 对于一个类来说,最最基础的三类成员函数莫过于:构造函数,析构函数以及拷贝函数 (copy构造函数和=重载函数).即使你的类没有为这些函数做出定义,C++ 也会自动为你创建.本文将讲述的是 C++ ...

  8. 判断手机电脑微信 js

    if ((navigator.userAgent.match(/(MicroMessenger)/i))) { //微信浏览器 //location.href=""; } else ...

  9. gradle构建项目失败:Unzipping /home/.gradle/wrapper/dists/gradle-3.3-all/55gk2rcmfc6p2dg9u9ohc3hw9/gradle-3.3-all.zip to /home/.gradle/wrapper/dists/gradle-3.3-all/55gk2rcmfc6p2dg9u9ohc3hw9

    Unzipping /home/.gradle/wrapper/dists/gradle-3.3-all/55gk2rcmfc6p2dg9u9ohc3hw9/gradle-3.3-all.zip to ...

  10. Java Map在遍历过程中删除元素

    Java中的Map如果在遍历过程中要删除元素,除非通过迭代器自己的remove()方法,否则就会导致抛出ConcurrentModificationException异常.JDK文档中是这么描述的: ...