简介
线程同步——这是一个很常见的面试题,那么实现线程同步有哪些方式呢?百度一下可以搜出很多相关文章,例如加锁,条件控制,信号量控制等等。那么Python提供了哪些方式呢?我们下面来看看。
目录
正文
基本锁 Lock
关键方法:
acquire:加锁
release:解锁
样例展示:
使用方式很简单,先加锁,再解锁,这样可以保证读取文件的顺序是一致的
import threading
lock = threading.Lock()
def readtxt(id):
lock.acquire()
with open("test.txt", mode="r", encoding="utf-8") as test:
for i in test.readlines():
time.sleep(0.1)
print("线程"+id,"读模式:",i)
print(i)
lock.release()
for i in range(2):
threading.Thread(target=readtxt, args={str(i)}).start()
源码分析:
源码使用的是Python内置的_thread模块实现锁的功能,再往下暂时就看不到了
import _thread
_allocate_lock = _thread.allocate_lock
Lock = _allocate_lock
# python内置_thread线程模块
def allocate_lock() -> LockType: ...
递归锁 RLock
关键方法:
acquire:加锁
release:解锁
样例展示:
和基本锁的用法基本相同,唯一不同的是基本锁在同一线程只能加一个锁,加多了会报错。而递归锁可以同时嵌套多个锁,只要按照加锁锁的数量和顺序,相应解锁。
import threading
rlock = threading.RLock()
def readtxt(id):
rlock.acquire()
rlock.acquire()
with open("test.txt", mode="r", encoding="utf-8") as test:
for i in test.readlines():
time.sleep(0.1)
print("线程"+id,"读模式:",i)
rlock.release()
rlock.release()
for i in range(2):
threading.Thread(target=readtxt, args={str(i)}).start()
源码分析:
关键在于如何实现递归添加锁的。
- 判断Python内置_thread模块是否存在支持RLock的方法,存在则直接使用,不存在就自己实现(源码中没有发现_thread支持RLock方法)
- 每次加锁前先判断当前锁ID是否存在,如果存在就计数(count)+1,不存在就创建锁,设置锁的拥有者,计数设置为1
- 每次解锁先计数(count)-1,然后判断计数(count)是否清零,0才解锁,锁的拥有者设置为None
import _thread
get_ident = _thread.get_ident
try:
_CRLock = _thread.RLock
except AttributeError:
_CRLock = None
_PyRLock = _RLock
def RLock(*args, **kwargs):
if _CRLock is None:
return _PyRLock(*args, **kwargs)
return _CRLock(*args, **kwargs)
class _RLock:
def __init__(