11-4 线程同步Lock,Condition

利用锁的机制,给共享变量操作时上锁,保证赋值操作正常进行

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
天猫精灵 : 我们来对古诗吧 
小爱同学 : 好啊 
天猫精灵 : 我住长江头 
小爱同学 : 君住长江尾 
天猫精灵 : 日日思君不见君 
小爱同学 : 共饮长江水 
天猫精灵 : 此水几时休 
小爱同学 : 此恨何时已 
天猫精灵 : 只愿君心似我心 
小爱同学 : 定不负相思意 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值