zoukankan      html  css  js  c++  java
  • Python 中的Lock与RLock

    摘要

    由于多线程共享进程的资源和地址空间,因此,在对这些公共资源进行操作时,为了防止这些公共资源出现异常的结果,必须考虑线程的同步和互斥问题。
    为什么加锁:1、用于非线程安全, 2、控制一段代码,确保其不产生调度混乱。

    threading.Lock的用法

    下面是一个python多线程的例子:

    import threading
    count = 0
    
    def print_time(threadName):
        global count
        c=0
        while(c<100):
            c+=1
            count+=1
            print("{0}: set count to {1}".format( threadName, count) )
    
    try:
        threading.Thread( target=print_time, args=("Thread-1", ) ).start()
        threading.Thread( target=print_time, args=("Thread-2", ) ).start()
        threading.Thread( target=print_time, args=("Thread-3", ) ).start()
    except Exception as e:
        print("Error: unable to start thread")
    

    在这个例子中,我们start了3个线程,每个线程都会对全局资源count进行改写操作。得到的结果如下,每个thread都会交替对count值进行修改。

    Thread-1: set count to 198
    Thread-2: set count to 199
    Thread-1: set count to 200
    Thread-2: set count to 201
    Thread-1: set count to 202
    Thread-2: set count to 203
    Thread-1: set count to 204
    Thread-2: set count to 205
    

    我们可以对上例中的print_time()中访问资源的代码加锁,就可以把这个函数变为线程安全的函数。具体代码如下:

    import threading
    
    count = 0
    lock = threading.Lock()
    
    def print_time(threadName):
        global count
    
        c=0
        with lock:
            while(c<100):
                c+=1
                count+=1
                print("{0}: set count to {1}".format( threadName, count) )
    
    try:
        threading.Thread( target=print_time, args=("Thread-1", ) ).start()
        threading.Thread( target=print_time, args=("Thread-2", ) ).start()
        threading.Thread( target=print_time, args=("Thread-3", ) ).start()
    except Exception as e:
        print("Error: unable to start thread")
    

    通过threading.Lock(),就能实现加锁。这样每个thread对count进行改动期间while(c<100),就不会有其它的thread插入进来改动count。得到的输出如下:

    Thread-2: set count to 199
    Thread-2: set count to 200
    Thread-3: set count to 201
    Thread-3: set count to 202
    Thread-3: set count to 203
    Thread-3: set count to 204
    

    锁的使用,有两种方法,上面的是最简单的通过with lock来操作。

    还有另一种用法,是通过Lock的acquire()和release()函数来控制加锁和解锁,如下例,得到的结果和上例相同:

    import threading
    
    count = 0
    lock = threading.Lock()
    
    def print_time(threadName):
        global count
        
        c=0
        if(lock.acquire()):
            while(c<100):
                c+=1
                count+=1
                print("{0}: set count to {1}".format( threadName, count) )
            lock.release()
    try:
        threading.Thread( target=print_time, args=("Thread-1", ) ).start()
        threading.Thread( target=print_time, args=("Thread-2", ) ).start()
        threading.Thread( target=print_time, args=("Thread-3", ) ).start()
    except Exception as e:
        print("Error: unable to start thread")
    

    Lock与RLock的区别

    在threading模块中,定义两种类型的琐:threading.Lock和threading.RLock。它们之间有一点细微的区别,通过比较下面两段代码来说明:

    import threading  
    lock = threading.Lock() #Lock对象  
    lock.acquire()  
    lock.acquire()  #产生了死琐。  
    lock.release()  
    lock.release()  
    
    import threading  
    rLock = threading.RLock()  #RLock对象  
    rLock.acquire()  
    rLock.acquire() #在同一线程内,程序不会堵塞。  
    rLock.release()  
    rLock.release()  
    

    这两种琐的主要区别是:RLock允许在同一线程中被多次acquire。而Lock却不允许这种情况。注意:如果使用RLock,那么acquire和release必须成对出现,即调用了n次acquire,必须调用n次的release才能真正释放所占用的琐。

  • 相关阅读:
    如何巧妙着运用「位运算」来解决问题?
    一文读懂一台计算机是如何把数据发送给另一台计算机的
    Java集合与泛型中的几个陷阱,你掉进了几个?
    【链表问题】打卡10:将搜索二叉树转换成双向链表
    【链表问题】打卡9:将单链表的每K个节点之间逆序
    【链表问题】打卡8:复制含有随机指针节点的链表
    单例模式中的volatile关键字
    链表回文判断(基于链表反转)—Java实现
    设计模式之单例模式
    Spring的IoC与AOP的理解
  • 原文地址:https://www.cnblogs.com/gmhappy/p/11863962.html
Copyright © 2011-2022 走看看