读写锁的典型使用场景

读写锁(Read-Write Lock,也称为共享-独占锁)是一种特殊的同步机制,它允许多个线程同时读取共享资源,但写入时必须是独占的。这种锁在读多写少的场景下可以显著提高并发性能。


读写锁的典型使用场景

1. 缓存系统(Cache)

  • 场景:缓存数据通常会被频繁读取(高并发读),但更新频率较低(低频写)。
  • 读写锁的作用
    • 多个线程可以同时读取缓存(共享读锁)。
    • 当缓存需要更新时,获取写锁(独占),阻塞所有读/写操作,保证数据一致性。
  • 示例
    from threading import RLock, Thread
    from time import sleep
    
    class Cache:
        def __init__(self):
            self.data = {}
            self.lock = RLock()  # 读写锁(Python 可用 `threading.RLock` 或第三方库)
    
        def get(self, key):
            with self.lock:
                return self.data.get(key)
    
        def set(self, key, value):
            with self.lock:
                self.data[key] = value
    
    # 多个线程可以并发读,但写时会阻塞
    

2. 数据库(Database)

  • 场景:数据库查询(SELECT)远多于更新(INSERT/UPDATE/DELETE)。
  • 读写锁的作用
    • 多个事务可以并发读取数据(共享读锁)。
    • 写入时获取写锁,防止脏读、不可重复读等问题。
  • 示例(伪代码):
    -- MySQL 的共享锁(读锁)和排他锁(写锁)
    SELECT * FROM table WHERE id = 1 LOCK IN SHARE MODE;  -- 读锁
    SELECT * FROM table WHERE id = 1 FOR UPDATE;          -- 写锁
    

3. 文件系统(File System)

  • 场景:多个进程/线程读取文件,但写入较少(如配置文件、日志文件)。
  • 读写锁的作用
    • 多个线程可以同时读取文件内容(共享读锁)。
    • 写入文件时,必须获取写锁,避免数据损坏。
  • 示例(Python):
    import threading
    
    class FileManager:
        def __init__(self, filename):
            self.filename = filename
            self.rw_lock = threading.RLock()
    
        def read(self):
            with self.rw_lock:
                with open(self.filename, "r") as f:
                    return f.read()
    
        def write(self, data):
            with self.rw_lock:
                with open(self.filename, "w") as f:
                    f.write(data)
    

4. 内存数据结构(如 ConcurrentHashMap

  • 场景:高并发访问 Map,但写入较少(如配置管理、全局状态存储)。
  • 读写锁的作用
    • 多个线程可以并发读取 Map 数据(共享读锁)。
    • 更新 Map 时,获取写锁,保证线程安全。
  • 示例(Java ReentrantReadWriteLock):
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    public class SafeMap<K, V> {
        private final Map<K, V> map = new HashMap<>();
        private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    
        public V get(K key) {
            rwLock.readLock().lock();
            try {
                return map.get(key);
            } finally {
                rwLock.readLock().unlock();
            }
        }
    
        public void put(K key, V value) {
            rwLock.writeLock().lock();
            try {
                map.put(key, value);
            } finally {
                rwLock.writeLock().unlock();
            }
        }
    }
    

5. 股票行情系统(高频读,低频更新)

  • 场景:股票价格会被大量查询,但更新频率较低(如每秒更新一次)。
  • 读写锁的作用
    • 多个客户端可以并发读取股票价格(共享读锁)。
    • 更新价格时,获取写锁,保证数据一致性。
  • 示例(伪代码):
    stock_price = 100.0
    rw_lock = threading.RLock()
    
    def get_price():
        with rw_lock:
            return stock_price
    
    def update_price(new_price):
        with rw_lock:
            stock_price = new_price
    

读写锁 vs 普通互斥锁

场景 读写锁(Read-Write Lock) 普通互斥锁(Mutex)
读操作 允许多个线程同时读 同一时间仅允许一个线程访问
写操作 仅允许一个线程写,阻塞所有读/写 仅允许一个线程访问
适用场景 读多写少(如缓存、数据库) 读写频率相当或写多读少
性能 高并发读时性能更好 所有操作串行化,性能较低

Python 中的读写锁

Python 标准库没有直接提供读写锁,但可以通过 threading.RLock 或第三方库(如 readerwriterlock)实现:

from readerwriterlock import rwlock

lock = rwlock.RWLockFair()
data = {}

def read_data(key):
    with lock.gen_rlock():  # 读锁
        return data.get(key)

def write_data(key, value):
    with lock.gen_wlock():  # 写锁
        data[key] = value

总结

使用读写锁的场景

  • 读操作远多于写操作(如缓存、数据库查询)。
  • 需要高并发读取,但写入较少(如配置文件、股票行情)。
  • 希望减少锁竞争,提高性能。

不适合读写锁的场景

  • 读写频率相当,或写操作较多(此时普通互斥锁可能更简单高效)。
  • 需要严格的实时一致性(读写锁可能导致写饥饿)。

根据业务场景选择合适的锁机制,能显著提高并发性能! 🚀

posted @ 2025-08-18 14:26  我不是萧海哇~~~  阅读(41)  评论(0)    收藏  举报