美文网首页
11-4 线程同步Lock,Condition

11-4 线程同步Lock,Condition

作者: 正在努力ing | 来源:发表于2018-08-26 15:40 被阅读0次

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

    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
    天猫精灵 : 我们来对古诗吧 
    小爱同学 : 好啊 
    天猫精灵 : 我住长江头 
    小爱同学 : 君住长江尾 
    天猫精灵 : 日日思君不见君 
    小爱同学 : 共饮长江水 
    天猫精灵 : 此水几时休 
    小爱同学 : 此恨何时已 
    天猫精灵 : 只愿君心似我心 
    小爱同学 : 定不负相思意 
    

    相关文章

      网友评论

          本文标题:11-4 线程同步Lock,Condition

          本文链接:https://www.haomeiwen.com/subject/dcyoiftx.html