Python 怎么实现读写锁呢

文章介绍了Python中没有内置的读写锁,但可以通过编程实现。提供了一个简单的读写锁实现,并讨论了其不公平性。读写锁分为读优先和写优先,文中以读优先为例,并提出了改进方案,以支持自定义优先级,包括使用条件变量来处理线程间的通信和等待策略。
摘要由CSDN通过智能技术生成

Python 提供的多线程模型中并没有提供读写锁,读写锁相对于单纯的互斥锁,适用性更高,可以多个线程同时占用读模式的读写锁,但是只能一个线程占用写模式的读写锁。

通俗点说就是当没有写锁时,就可以加读锁且任意线程可以同时加;而写锁只能有一个线程,且必须在没有读锁时才能加上。

简单的实现

import threadingclass RWlock(object): def __init__(self): self._lock = threading.Lock() self._extra = threading.Lock() self.read_num = 0 def read_acquire(self): with self._extra: self.read_num += 1 if self.read_num == 1: self._lock.acquire() def read_release(self): with self._extra: self.read_num -= 1 if self.read_num == 0: self._lock.release() def write_acquire(self): self._lock.acquire() def write_release(self): self._lock.release()

这是读写锁的一个简单的实现,self.read_num 用来保存获得读锁的线程数,这个属性属于临界区,对其操作也要加锁,所以这里需要一个保护内部数据的额外的锁 self._extra 。

但是这个锁是不公平的。理想情况下,线程获得所的机会应该是一样的,不管线程是读操作还是写操作。而从上述代码可以看到,读请求都会立即设置 self.read_num += 1,不管有没有获得锁,而写请求想要获得锁还得等待 read_num为 0 。

所以这个就造成了只有锁没有被占用或者没有读请求时,可以获得写权限。我们应该想办法避免读模式锁长期占用。

读写锁的优先级

读写锁也有分 读优先 和 写优先。上面的代码就属于读优先。

如果要改成写优先,那就换成去记录写线程的引用计数,读和写在同时竞争时,可以让写线程增加写的计数,这样可使读线程的读锁一直获取不到, 因为读线程要先判断写的引用计数,若不为0,则等待其为 0,然后进行读。这部分代码不罗列了。

但这样显然不够灵活。我们不需要两个相似的读写锁类。我们希望重构我们代码,使它更强大。

改进

为了能够满足自定义优先级的读写锁,要记录等待的读写线程数,并且需要两个条件threading.Condition 用来处理哪方优先的通知。计数引用可以扩大语义:正数:表示正在读操作的线程数,负数:表示正在写操作的线程数(最多-1)

在获取读操作时,先然后判断时候有等待的写线程,没有,进行读操作,有,则等待读的计数加 1 后等待 Condition 通知;等待读的计数减 1,计数引用加 1,继续读操作,若条件不成立,循环等待;

在获取写操作时,若锁没有被占用,引用计数减 1,若被占用,等待写线程数加 1,等待写条件 Condition 的通知。

读模式和写模式的释放都是一样,需要根据判断去通知对应的 Condition:

class RWLock(object): def __init__(self): self.lock = threading.Lock() self.rcond

————————————————

来源:https://www.weidianyuedu.com

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
读写锁是一种用于多线程编程的同步机制,它允许多个线程同时读取共享资源,但只允许一个线程写入共享资源。在Python中,可以使用threading模块中的RLock类来实现读写锁。 下面是一个使用Python实现读写锁的例子: ```python import threading class RWLock: def __init__(self): self._lock = threading.Lock() self._read_lock = threading.Lock() self._write_lock = threading.Lock() self._read_count = 0 def acquire_read(self): with self._lock: self._read_count += 1 if self._read_count == 1: self._write_lock.acquire() self._read_lock.acquire() self._read_lock.release() def release_read(self): with self._lock: self._read_count -= 1 if self._read_count == 0: self._write_lock.release() def acquire_write(self): self._write_lock.acquire() def release_write(self): self._write_lock.release() ``` 在上面的代码中,我们定义了一个RWLock类,它包含了acquire_read、release_read、acquire_write和release_write等方法。acquire_read方法用于获取读锁,release_read方法用于释放读锁,acquire_write方法用于获取写锁,release_write方法用于释放写锁。 使用读写锁的示例代码如下: ```python lock = RWLock() def read_func(): lock.acquire_read() # 读取共享资源的操作 lock.release_read() def write_func(): lock.acquire_write() # 写入共享资源的操作 lock.release_write() # 创建多个读线程和写线程 read_threads = [threading.Thread(target=read_func) for _ in range(5)] write_threads = [threading.Thread(target=write_func) for _ in range(2)] # 启动线程 for thread in read_threads + write_threads: thread.start() # 等待线程结束 for thread in read_threads + write_threads: thread.join() ``` 上面的代码中,我们创建了5个读线程和2个写线程,并通过调用start方法启动线程。然后,我们使用join方法等待所有线程执行完毕。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值