python中--锁-死锁-递归锁-线程锁--生产者消费者模型
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python中--锁-死锁-递归锁-线程锁--生产者消费者模型,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含6820字,纯文字阅读大概需要10分钟。
内容图文
Lock 互斥锁
进程之间数据安全的问题
把要保护的数据锁起来,每次只有一个人能访问
注意:
1.锁不要轻易的使用,容易造成死锁现象(我们写代码一般不会用大,都是用内部封装好的)
2.锁只在处理数据的部分加,来保证数据安全(只有在争抢数据的换届加锁处理即可)
- lock.acquire() 取钥匙
- lock.release() 还钥匙
# @时间 : 2020/6/29 14:41
# @作者 : 子清
from multiprocessing import Process, Lock
import json
import time
def show_ticket(i):
with open('ticket', encoding='utf-8', mode='r') as f:
ret = json.load(f)
time.sleep(0.5)
print(f'{i}:还剩{ret["count"]}张票')
def buy_ticket(i):
with open('ticket',encoding='utf-8',mode='r') as f:
ret = json.load(f)
if ret['count'] > 0:
ret['count'] -= 1
print(f'{i}买票成功')
time.sleep(0.2)
with open('ticket',encoding='utf-8',mode='w') as f:
json.dump(ret,f)
def get_ticket(i,lock):
show_ticket(i)
lock.acquire()
buy_ticket(i)
lock.release()
if __name__ == '__main__':
lock = Lock()
for i in range(10):
p1 = Process(target=get_ticket, args=(i,lock))
p1.start()
其中的取钥匙和还钥匙动作可以简写 with lock:
尽量用这个
代替acquire和release 并且在此基础上做了一些异常处理,保证即便一个进程的代码出错退出了,也会归还钥匙
def get_ticket(i,lock):
show_ticket(i)
lock.acquire()
buy_ticket(i)
lock.release()
# ------等同于-------
def get_ticket(i,lock):
show_ticket(i)
with lock:
buy_ticket(i)
from multiprocessing import Lock # 互斥锁,不能再同一个进程中连续acquire多次
lock = Lock()
lock.acquire()
print(1)
lock.acquire()
print(2)
# --------------解决办法,把acquire和release对应起来,一次取一次还
from multiprocessing import Lock # 互斥锁,不能再同一个进程中连续acquire多次
lock = Lock()
lock.acquire() # 取
print(1)
lock.release() # 还
lock.acquire() # 取
print(2)
lock.release() # 还
线程锁
+= -= *= /= while if 数据不安全 +和赋值是分开的两个操作
append pop 数据安全, 列表中的方法或者字典中的方法去操作全局变量的时候 数据安全的
线程之间也存在数据不安全
- 加锁解决
from threading import Thread,Lock
n = 0
def foo(lock):
for i in range(100000):
global n
with lock:
n += 1
def son(lock):
for i in range(100000):
global n
with lock:
n -= 1
if __name__ == '__main__':
t_l = []
lock = Lock()
for i in range(2):
t = Thread(target=foo,args=(lock,))
t.start()
t1 = Thread(target=son,args=(lock,))
t1.start()
t_l.append(t)
t_l.append(t1)
for i in t_l:
i.join()
print(n)
不要操作全局变量, 不要在类里操作静态变量
递归锁
from threading import Lock,RLock
Lock
互斥锁 RLock
递归锁(recursion)
递归锁相当于万能钥匙,锁里面还有锁也能进(递归),同样的你进了多少锁(acquire),你就要出来多少次(release)。
- 用法一样,都是
acquire()和release()
from threading import Lock,RLock
l = Lock()
l.acquire()
# l.acquire() # 互斥锁不能连续acquire多次
print('要锁住的代码')
l.release()
rl = RLock()
rl.acquire() # 递归锁在同一个线程中可以被acquire多次
rl.acquire()
rl.acquire()
print('要锁着的代码')
rl.release()
from threading import Lock,RLock,Thread
def func(i,lock):
lock.acquire()
print(f'{i}--start...')
lock.release()
print(f'{i}--end...')
if __name__ == '__main__':
lock = Lock()
for i in range(5):
t = Thread(target=func, args=(i, lock))
t.start()
#-------------------------------------
from threading import Lock,RLock,Thread
def func(i,lock):
lock.acquire()
lock.acquire()
lock.acquire()
print(f'{i}--start...')
lock.release()
lock.release()
lock.release()
print(f'{i}--end...')
if __name__ == '__main__':
lock = RLock()
for i in range(5):
t = Thread(target=func, args=(i, lock))
t.start()
死锁
互斥锁效率高,递归锁效率高低
递归锁 效率低 但是解决死锁现象有奇效
互斥锁 效率高 但是多把锁容易出现死锁现象
死锁现象是怎么产生的?
- 多把(互斥/递归)锁 并且在多个线程中 交叉使用
from threading import Thread, Lock, RLock
import time
noodle_lock = Lock() # 互斥锁
fork_lock = Lock() # 互斥锁
# 实例化了两把锁
def eat(name):
noodle_lock.acquire()
print(name, '抢到了面')
fork_lock.acquire()
print(name, '抢到了叉子')
print(name, '吃面')
time.sleep(1)
noodle_lock.release()
print(name, '放回了面')
fork_lock.release()
print(name, '放回了叉子')
def eat2(name):
fork_lock.acquire()
print(name, '抢到了叉子')
noodle_lock.acquire()
print(name, '抢到了面')
print(name, '吃面')
time.sleep(1)
fork_lock.release()
print(name, '放回了叉子')
noodle_lock.release()
print(name, '放回了面')
t = Thread(target=eat, args=('alex',)).start()
t1 = Thread(target=eat2, args=('wusir',)).start()
t2 = Thread(target=eat, args=('taibai',)).start()
t3 = Thread(target=eat2, args=('egon',)).start()
- 如果是互斥锁,出现了死锁现象,最快速的解决方案把所有的互斥锁都改成同一把递归锁(注意:是同一把!!)
- 但是程序效率会降低
from threading import Thread, Lock, RLock
import time
fork_lock = noodle_lock = RLock() # 这里换成RLock递归锁,并且这两把锁是同一把锁,只实例化了一把锁
# ----------------下面都没改,主要是上面-----------
def eat(name):
noodle_lock.acquire()
print(name, '抢到了面')
fork_lock.acquire()
print(name, '抢到了叉子')
print(name, '吃面')
time.sleep(1)
noodle_lock.release()
print(name, '放回了面')
fork_lock.release()
print(name, '放回了叉子')
def eat2(name):
fork_lock.acquire()
print(name, '抢到了叉子')
noodle_lock.acquire()
print(name, '抢到了面')
print(name, '吃面')
time.sleep(1)
fork_lock.release()
print(name, '放回了叉子')
noodle_lock.release()
print(name, '放回了面')
t = Thread(target=eat, args=('alex',)).start()
t1 = Thread(target=eat2, args=('wusir',)).start()
t2 = Thread(target=eat, args=('taibai',)).start()
t3 = Thread(target=eat2, args=('egon',)).start()
- 或者把两把锁改成一把(互斥锁和递归锁都行)
from threading import Thread, Lock, RLock
import time
fork_noodle_lock = Lock() # 这里用的互斥锁,递归锁也是可以的
def eat(name):
fork_noodle_lock.acquire() # 两把改成一把
print(name, '抢到了面')
print(name, '抢到了叉子')
print(name, '吃面')
time.sleep(0.1)
fork_noodle_lock.release()
print(name, '放回了面')
print(name, '放回了叉子')
def eat2(name):
fork_noodle_lock.acquire()
print(name, '抢到了叉子')
print(name, '抢到了面')
print(name, '吃面')
time.sleep(1)
fork_noodle_lock.release()
print(name, '放回了叉子')
print(name, '放回了面')
t = Thread(target=eat, args=('alex',)).start()
t1 = Thread(target=eat2, args=('wusir',)).start()
t2 = Thread(target=eat, args=('taibai',)).start()
t3 = Thread(target=eat2, args=('egon',)).start()
生产者消费者模型
consumer消费者,producer生产者
本质:就是让生产数据和消费数据的效率达到平衡并且最大化的效率
from multiprocessing import Process, Queue
import time, random
def producer(q, name, food): # 生产者:通常在放数据之前需要先通过某些代码来获取数据
for i in range(10):
foodi = f'{food}{i}'
time.sleep(random.random())
q.put(foodi)
print(f'{name}生产了{foodi}')
def consumer(q, name): # 消费者:通常取到数据之后还要进行某些操作
while 1:
food = q.get()
if food:
print(f'{name}吃了{food}')
else:
break
if __name__ == '__main__':
q = Queue()
p1 = Process(target=producer, args=(q, 'ziqing', '樱桃'))
p2 = Process(target=producer, args=(q, 'zxc', '草莓'))
c1 = Process(target=consumer, args=(q, '太白'))
c2 = Process(target=consumer, args=(q, 'alex'))
p1.start()
p2.start()
c1.start()
c2.start()
p1.join()
p2.join()
q.put(None)
q.put(None)
内容总结
以上是互联网集市为您收集整理的python中--锁-死锁-递归锁-线程锁--生产者消费者模型全部内容,希望文章能够帮你解决python中--锁-死锁-递归锁-线程锁--生产者消费者模型所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。