互斥锁/读写锁实战

假如原代码为

GLOBAL_CONF = None


def global_conf():
    return GLOBAL_CONF


def set_global_conf(conf):
    print("set global config: ", conf)
    global GLOBAL_CONF
    GLOBAL_CONF = conf

def cb(data):
    print("callback func is called, config changed: ", data)
    global GLOBAL_CONF
    GLOBAL_CONF = data

这段代码通过global_conf() 读取全局变量,初始化时通过set_global_conf() 设置全局变量的初始值,并配合回调函数cb() 更新全局变量

互斥锁

python标准库只提供了互斥锁RLock

互斥锁/读写锁实战_第1张图片

读写锁+共享变量

相比互斥锁,读写锁适用于读操作频繁、写操作较少的场景,可以提高并发性能

若使用读写锁,还需要增加共享变量,from multiprocessing import Process, Manager

这是因为在多进程环境中,全局变量是每个进程的私有副本。由于每个进程都有自己的内存空间,因此一个进程对GLOBAL_CONF的修改不会影响其他进程

from readerwriterlock import rwlock
# 获取七彩石的代码表明这个框架是多进程的(master+worker),同时没看到跨机器服务调用的分布式的问题(都是单个服务实例内),这里应该采用多进程的读写锁
# 相比互斥锁,读写锁适用于读操作频繁、写操作较少的场景,可以提高并发性能
from multiprocessing import Process, Manager
LOCK = rwlock.RWLockFair()

# 注意 让多个进程共享同一个全局状态(否则在多进程环境中,全局变量是每个进程的私有副本。由于每个进程都有自己的内存空间,因此一个进程对GLOBAL_CONF的修改不会影响其他进程)
manager = Manager()
GLOBAL_CONF = manager.Value('JSON', None)


def global_conf():
    with LOCK.gen_rlock():  # 获取配置,加读锁
        return GLOBAL_CONF.value


def set_global_conf(conf):
    with LOCK.gen_wlock(): # 设置配置,加写锁
        print("set global config: ", conf)
        GLOBAL_CONF.value = conf

def cb(data):
    # 配置变更回调函数,加写锁
    with LOCK.gen_wlock():
        print("callback func is called, config changed: ", data)
        GLOBAL_CONF.value = data

if __name__ == "__main__":
    # 测试读写锁
    # 启动多个读进程和写进程
    from multiprocessing import Process, Manager
    import time

    def reader_process(id):
        """读进程"""
        for _ in range(3):  # 模拟多次读取
            conf = global_conf()
            print(f"Reader {id} read config: {conf}")
            time.sleep(1)  # 模拟耗时操作


    def writer_process(id):
        """写进程"""
        for i in range(2):  # 模拟多次写入
            new_conf = f"config_{id}_{i}"
            set_global_conf(new_conf)
            time.sleep(2)  # 模拟耗时操作

    processes = [] # 五个进程同时开始,先后顺序的差异由进程调度导致
    for i in range(3):  # 3个读进程
        p = Process(target=reader_process, args=(i,)) #创建进程对象
        processes.append(p)
        p.start() # 启动刚创建的进程,操作系统会为该进程分配资源并开始执行目标函数,该进程将并行运行,不会阻塞主进程的执行

    for i in range(2):  # 2个写进程
        p = Process(target=writer_process, args=(i,))
        processes.append(p)
        p.start()

    # 等待所有进程完成
    for p in processes:
        p.join() # 使主进程等待进程 p 完成。调用 join() 后,主进程会阻塞,直到 p 进程执行完成

    print("All processes finished.")

你可能感兴趣的:(AI工程落地,服务器)