1 死锁问题(递归锁,可重入锁)
1 所谓死锁:是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程,如下就是死锁
2 可重入锁,递归锁
# from threading import Thread, Lock
# import time
# import random
#
#
# def eat1(lock_1, lock_2, name):
# lock_1.acquire()
# print('%s:拿到了筷子' % name)
# time.sleep(random.random())
# lock_2.acquire()
# print('%s:拿到了面条' % name)
# print('开始吃面')
# time.sleep(random.random())
# lock_2.release()
# print('%s放下了面条' % name)
# lock_1.release()
# print('%s放下了筷子' % name)
#
#
# def eat2(lock_1, lock_2, name):
# lock_2.acquire()
# print('%s:拿到了面条' % name)
# time.sleep(random.random())
# lock_1.acquire()
# print('%s:拿到了筷子' % name)
# print('开始吃面')
# time.sleep(random.random())
# lock_1.release()
# print('%s放下了筷子' % name)
# lock_2.release()
# print('%s放下了面条' % name)
#
#
# if __name__ == '__main__':
# lock_1 = Lock()
# lock_2 = Lock()
# for i in ['张三', '李四', '王五']:
# t = Thread(target=eat1, args=[lock_1, lock_2, i])
# t.start()
# for i in ['赵6', '往7', '傻逼']:
# t = Thread(target=eat2, args=[lock_1, lock_2, i])
# t.start()
### 解决死锁问题 RLock:可重入,可以重复acquire,获得几次,就要释放几次
from threading import Thread, Lock,RLock
import time
import random
def eat1(lock_1, lock_2, name):
lock_1.acquire()
print('%s:拿到了筷子' % name)
time.sleep(random.random())
lock_2.acquire()
print('%s:拿到了面条' % name)
print('开始吃面')
time.sleep(random.random())
lock_2.release()
print('%s放下了面条' % name)
lock_1.release()
print('%s放下了筷子' % name)
def eat2(lock_1, lock_2, name):
lock_2.acquire()
print('%s:拿到了面条' % name)
time.sleep(random.random())
lock_1.acquire()
print('%s:拿到了筷子' % name)
print('开始吃面')
time.sleep(random.random())
lock_1.release()
print('%s放下了筷子' % name)
lock_2.release()
print('%s放下了面条' % name)
if __name__ == '__main__':
lock_1 = RLock()
lock_2 = lock_1
# lock_1 = Lock()
# lock_2 = lock_1
for i in ['张三', '李四', '王五']:
t = Thread(target=eat1, args=[lock_1, lock_2, i])
t.start()
for i in ['赵6', '往7', '傻逼']:
t = Thread(target=eat2, args=[lock_1, lock_2, i])
t.start()
2 线程队列
1 线程Queue,解决线程间数据共享的问题
2 线程间数据共享可以使用共享变量(可能会存在并发安全的问题)
from threading import Thread
from queue import Queue,LifoQueue,PriorityQueue # 线程queue
# Queue:先进先出
#LifoQueue:后进先出
#PriorityQueue:优先级队列
# import time
# def task(queue):
# time.sleep(3)
# queue.put('lqz')
#
#
#
# if __name__ == '__main__':
# queue=Queue()
# t=Thread(target=task,args=[queue,])
# t.start()
#
#
# res=queue.get()
# print(res)
# Queue:先进先出
# LifoQueue:后进先出
# PriorityQueue:优先级队列
if __name__ == '__main__':
# quque1=Queue()
#
# quque1.put(1)
# quque1.put(2)
# print(quque1.get())
# quque2=LifoQueue()
# quque2.put(1)
# quque2.put(2)
# print(quque2.get())
quque3=PriorityQueue()
quque3.put((1,'lqz'))
quque3.put((100,'egon'))
# 数字越小,优先级越高
print(quque3.get())
3 进程池,线程池
# 线程池,进程池都在这个模块下concurrent.futures
import time
import os
import random
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
# def task(n):
# print(os.getpid(), '开始执行了')
# time.sleep(random.random())
# return n * n
#
#
#
# def callback(result):
# print(result)
# if __name__ == '__main__':
# # 开进程池去执行
# # ProcessPoolExecutor实例化得到一个对象
# pool_p=ProcessPoolExecutor(3)
# # ll=[]
# # for i in range(10):
# # # 把任务提交到进程池执行
# # f=pool_p.submit(task,n=i)
# # ll.append(f)
# #
# # # 等待所有子进程执行完成,主进程在执行
# # pool_p.shutdown()
# #
# # for l in ll:
# # res=l.result() # 取到当前进程执行任务的返回值
# # print(res)
# #
# # print('我是主进程')
#
# # map取代for循环的,第一个参数是要执行的任务,第二个参数,是一个可迭代对象,迭代一次的结果,会传给任务
#
#
#
# # for i in range(10):
# # f=pool_p.submit(task,n=i)
# # 等同于上面
# # pool_p.map(task,range(10))
# # pool_p.shutdown()
# # print('主进程')
#
#
# ## 回调
# for i in range(10):
# pool_p.submit(task,n=i).add_done_callback()
def task(n):
print(os.getpid(), '开始执行了')
time.sleep(1)
return n * n
def callback(result):
print(result.result())
# if __name__ == '__main__':
# pool_p = ProcessPoolExecutor(3)
# for i in range(10):
# pool_p.submit(task, n=i).add_done_callback(callback)
#
'''
submit #把任务提交到进程池执行
shutdown #等待所有子进程执行完成,主进程在执行
result # 取到当前进程执行任务的返回值
map(了解) #map取代for循环的,第一个参数是要执行的任务,第二个参数,是一个可迭代对象,迭代一次的结果,会传给任务
add_done_callback:回调
'''
if __name__ == '__main__':
pool_p = ThreadPoolExecutor(3)
for i in range(10):
pool_p.submit(task, n=i).add_done_callback(callback)
4 协程介绍
1 协程是:程序级别的切换,单线程下实现并发
python的线程属于内核级别的,即由操作系统控制调度(如单线程遇到io或执行时间过长就会被迫交出cpu执行权限,切换其他线程运行)
单线程内开启协程,一旦遇到io,就会从应用程序级别(而非操作系统)控制切换,以此来提升效率(!!!非io操作的切换与效率无关)
5 greenlet模块(初级模块,实现了保存状态加切换)
# 安装第三方模块:在命令行下
# pip3 install greenlet
# pip3 uninstall greenlet 卸载第三方模块
# pip3 list # 列出当前解释器环境下安装的第三方模块
from greenlet import greenlet
def eat(name):
print(name,'在吃了一口')
g2.switch(name)
print(name,'在吃了第二口')
g2.switch()
def play(name):
print(name, '玩了一下')
g1.switch()
print(name, '玩了第二下')
g1=greenlet(eat)
g2=greenlet(play)
g1.switch('egon')
6 gevent模块
## gevent模块,协程模块,遇到io可以自动切换
# pip3 install gevent
import gevent
import time
# def eat(name):
# print(name, '在吃了一口')
# # 遇到了io
# gevent.sleep(2)
#
# print(name, '在吃了第二口')
#
#
# def play(name):
# print(name, '玩了一下')
# # 遇到了io,是gevent的io
# gevent.sleep(3)
# print(name, '玩了第二下')
#
#
# res1 = gevent.spawn(eat, 'egon')
# res2 = gevent.spawn(play, 'egon')
#
#
# ctime=time.time()
# # res1.join()
# # res2.join() # 等地任务执行完成再执行下面那句
#
# gevent.joinall([res1,res2]) # 相当于上面那两句
# print('主线程')
# print(time.time()-ctime)
###使用原来的time的io,不会切,并且变成了串行
# def eat(name):
# print(name, '在吃了一口')
# time.sleep(2)
#
# print(name, '在吃了第二口')
#
#
# def play(name):
# print(name, '玩了一下')
# time.sleep(3)
# print(name, '玩了第二下')
#
#
# res1 = gevent.spawn(eat, 'egon')
# res2 = gevent.spawn(play, 'egon')
#
#
# ctime=time.time()
#
# gevent.joinall([res1,res2]) # 相当于上面那两句
# print('主线程')
# print(time.time()-ctime)
### time的io也要切换
# 猴子补丁:把原来的io全都替换成gevent的io
from gevent import monkey;monkey.patch_all()
def eat(name):
print(name, '在吃了一口')
time.sleep(2)
print(name, '在吃了第二口')
def play(name):
print(name, '玩了一下')
time.sleep(3)
print(name, '玩了第二下')
res1 = gevent.spawn(eat, 'egon')
res2 = gevent.spawn(play, 'egon')
ctime=time.time()
gevent.joinall([res1,res2]) # 相当于上面那两句
print('主线程')
print(time.time()-ctime)
7 asyncio
# 内置模块 python 3.4 推出这个模块,python作者主导的
import asyncio
import time
import threading
# 这个函数是协程函数
async def task():
res=threading.current_thread().getName()
print(res)
print('xxx')
await asyncio.sleep(2)
print('协程执行完成')
async def task2():
res=threading.current_thread().getName()
print(res)
print('2222')
await asyncio.sleep(3)
print('222协程执行完成')
ctime=time.time()
loop=asyncio.get_event_loop()
tasks=[task(),task2()]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
print(time.time()-ctime)