lock与Rlock的区别


1、lock与Rlock的区别

LocksRLocks

A Lock object can not be acquired again by any thread unless it is released by the thread which which is accessing the shared resource.

一个lock被释放前不能被其他线程获得acquire

An RLock object can be acquired numerous times by any thread.

一个Rlock可以被其他任意线程获得

A Lock object can be released by any thread.

一个lock可以被其他线程释放

An RLock object can only be released by the thread which acquired it.

Rlock只能被获得他的线程释放

A Lock object can be owned by one

lock被一个线程占有

An RLock object can be owned by many threads

Rlock可以被其他线程获得

Execution of a Lock object is faster.

lock的运行速度快

Execution of an RLock object is slower than a Lock object

运行速度比lock慢

 主要区别:在同一线程内,对RLock进行多次acquire()操作,程序不会阻塞。

=========================

eg1: 死锁

import threading
  
  
# initializing the shared resource
geek = 0
  
# creating a Lock object 
lock = threading.Lock()
  
# the below thread is accessing the
# shared resource
lock.acquire()
geek = geek + 1
  
# This thread will be blocked
lock.acquire() 
geek = geek + 2
lock.release()
  
# displaying the value of shared resource
print(geek)

----output--无数据输出 

eg2--OK:
# program to illustrate the use of RLocks
  
# importing the module
import threading
  
# initializing the shared resource
geek = 0
  
# creating an RLock object instead 
# of Lock object 
lock = threading.RLock()
  
# the below thread is trying to access 
# the shared resource
lock.acquire()
geek = geek + 1
  
# the below thread is trying to access 
# the shared resource 
lock.acquire() 
geek = geek + 2
lock.release()
lock.release()
  
# displaying the value of shared resource
print(geek)

output =3

=================

“lock = threading.Lock()”,这就是最普通的Lock;还有一种RLock锁,使用“lock = threading.RLock()”即可。

其实RLock和Lock很像,几乎一样,唯一的区别是RLock中可以继续上RLock锁,但是Lock锁不能这样做,Lock锁一旦这样做了,线程就会卡死。示例如下:

# coding=utf-8
import threading

# 定义RLock锁
lock = threading.RLock()

def fuck( thread_name ):
    lock.acquire() # 上锁
    ...
    lock.acquire() # 上锁 !!! 假设定义的不是RLock,而是Lock,那在这里机会卡死
    ...
    lock.release() # 解锁
    ...
    lock.release() # 解锁

threading.Thread( target=fuck, args=("fuck-1", ) ).start()
threading.Thread( target=fuck, args=("fuck-2", ) ).start()
threading.Thread( target=fuck, args=("fuck-3", ) ).start()

上述的示例如果换成with lock的方式,如下:

# coding=utf-8
import threading

# 定义RLock锁
lock = threading.RLock()

def fuck( thread_name ):
    with lock:
        ...
        with lock: # !!! 假设定义的不是RLock,而是Lock,那在这里机会卡死
            ...
    
threading.Thread( target=fuck, args=("fuck-1", ) ).start()
threading.Thread( target=fuck, args=("fuck-2", ) ).start()
threading.Thread( target=fuck, args=("fuck-3", ) ).start()

上述两个示例程序中,假设最初定义的不是RLock,而是Lock,那在示例代码中打叹号注释的位置直接卡死。

这时就会有人问道,为啥要在上锁状态中继续上锁呢?这不是傻X嘛?

原因:假如这是一个很复杂的多线程程序呢?比如函数中要使用一堆别的函数,届时,在不同的函数中就很有可能需要对某段代码要上锁,这时RLock的价值就体现了。

综上:对于简单的多线程代码使用Lock即可,对于复杂的多线程系统,优先使用RLock。