利用锁的机制,给共享变量操作时上锁,保证赋值操作正常进行
lock = Lock()
lock.acquire() # 上锁,保证操作唯一
total -= 1
lock.release() # 解锁,这样别人才可以用
import time
from threading import Lock,RLock,Condition,Thread
total = 0
lock = Lock()
def get_html():
global total
for i in range(1000):
lock.acquire()
total += 1
print("get_html is ",total)
lock.release()
def get_url():
global total
for i in range(1000):
lock.acquire()
total -= 1
print("get_url is ",total)
lock.release()
if __name__ == "__main__":
thread1 = Thread(target=get_html)
thread2 = Thread(target=get_url)
thread1.start()
thread2.start()
print("total is",total)
>>>
get_html is 1
get_html is 2
......
get_html is 35
get_html is 36
total is 36 #此时主进程语句执行完,等待其他进程的结束
get_html is 37
......
get_html is 50 # 变化
get_url is 49 # 变化
get_url is 48
.......
get_url is -76
但是用锁的缺点:
1 会降低性能
2 锁会引起死锁 : 上了锁,忘了解锁,就会这样
3 可以上多把锁,但是同时也要解多把锁
Condition 机制
condition 是一个类(基于锁实现的),让一个或者多个进程等待,直到这些进程被别的进程通知消息
源码
class Condition:
"""Class that implements a condition variable.
A condition variable allows one or more threads to wait until they are
notified by another thread.
If the lock argument is given and not None, it must be a Lock or RLock
object, and it is used as the underlying lock. Otherwise, a new RLock object
is created and used as the underlying lock.
"""
def __init__(self, lock=None):
if lock is None:
lock = RLock()
self._lock = lock
# Export the lock's acquire() and release() methods
self.acquire = lock.acquire
self.release = lock.release
# If the lock defines _release_save() and/or _acquire_restore(),
# these override the default implementations (which just call
# release() and acquire() on the lock). Ditto for _is_owned().
try:
self._release_save = lock._release_save
except AttributeError:
pass
try:
self._acquire_restore = lock._acquire_restore
except AttributeError:
pass
try:
self._is_owned = lock._is_owned
except AttributeError:
pass
self._waiters = _deque()
def wait(self, timeout=None):
"""
Wait until notified or until a timeout occurs.
"""
if not self._is_owned():
raise RuntimeError("cannot wait on un-acquired lock")
waiter = _allocate_lock() # 分配一把锁
waiter.acquire()
self._waiters.append(waiter) #self._waiters = _deque()是一个双向队列,把锁添加到双向列表中
saved_state = self._release_save()
gotit = False
try: # restore state no matter what (e.g., KeyboardInterrupt)
if timeout is None:
waiter.acquire()
gotit = True
else:
if timeout > 0:
gotit = waiter.acquire(True, timeout)
else:
gotit = waiter.acquire(False)
return gotit
finally:
self._acquire_restore(saved_state)
if not gotit:
try:
self._waiters.remove(waiter)
except ValueError:
pass
def notify(self, n=1):
"""Wake up one or more threads waiting on this condition, if any.
If the calling thread has not acquired the lock when this method is
called, a RuntimeError is raised.
This method wakes up at most n of the threads waiting for the condition
variable; it is a no-op if no threads are waiting.
"""
if not self._is_owned(): #判断有锁
raise RuntimeError("cannot notify on un-acquired lock")
all_waiters = self._waiters
waiters_to_notify = _deque(_islice(all_waiters, n))
if not waiters_to_notify:
return
for waiter in waiters_to_notify:
waiter.release()
try:
all_waiters.remove(waiter)
except ValueError:
pass
用法一 :
cond_a = Condition() # 实例化
cond_b = Condition()
cond_a.aquire() #获得锁
cond_b.aquire()
#A 进程等待
cond_a.wait()
#b 进程通过notify唤醒另外的处于wait的进程
cond_b.notify()
# 释放锁
cond_a.release()
cond_b.release()
用法二 :
使用with,这样就不需要写aquire和release
with cond:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
__title__ = ''
__author__ = 'Administrator'
__mtime__ = '2018/7/26'
# code is far away from bugs with the god animal protecting
I love animals. They taste delicious.
┏┓ ┏┓
┏┛┻━━━┛┻┓
┃ ☃ ┃
┃ ┳┛ ┗┳ ┃
┃ ┻ ┃
┗━┓ ┏━┛
┃ ┗━━━┓
┃ 神兽保佑 ┣┓
┃ 永无BUG! ┏┛
┗┓┓┏━┳┓┏┛
┃┫┫ ┃┫┫
┗┻┛ ┗┻┛
"""
from threading import Thread,Condition
class XiaoAI(Thread):
def __init__(self,cond):
self.cond = cond
super(XiaoAI, self).__init__(name="小爱同学")
def run(self):
with self.cond:
self.cond.wait()
print("{} : zai".format(self.name))
self.cond.notify()
self.cond.wait()
print("{} : 好啊 ".format(self.name))
self.cond.notify()
self.cond.wait()
print("{} : 君住长江尾 ".format(self.name))
self.cond.notify()
self.cond.wait()
print("{} : 共饮长江水 ".format(self.name))
self.cond.notify()
self.cond.wait()
print("{} : 此恨何时已 ".format(self.name))
self.cond.notify()
self.cond.wait()
print("{} : 定不负相思意 ".format(self.name))
self.cond.notify()
class TianMao(Thread):
def __init__(self,cond):
self.cond = cond
super().__init__(name="天猫精灵")
def run(self):
with self.cond:
print("{} : 小爱同学".format(self.name))
self.cond.notify()
self.cond.wait()
print("{} : 我们来对古诗吧 ".format(self.name))
self.cond.notify()
self.cond.wait()
print("{} : 我住长江头 ".format(self.name))
self.cond.notify()
self.cond.wait()
print("{} : 日日思君不见君 ".format(self.name))
self.cond.notify()
self.cond.wait()
print("{} : 此水几时休 ".format(self.name))
self.cond.notify()
self.cond.wait()
print("{} : 只愿君心似我心 ".format(self.name))
self.cond.notify()
self.cond.wait()
if __name__ == "__main__":
cond = Condition()
xiaoai = XiaoAI(cond)
tianmao = TianMao(cond)
xiaoai.start()
tianmao.start()
>>>
小爱同学 : zai
天猫精灵 : 我们来对古诗吧
小爱同学 : 好啊
天猫精灵 : 我住长江头
小爱同学 : 君住长江尾
天猫精灵 : 日日思君不见君
小爱同学 : 共饮长江水
天猫精灵 : 此水几时休
小爱同学 : 此恨何时已
天猫精灵 : 只愿君心似我心
小爱同学 : 定不负相思意
网友评论