Python中如何用Linux信号量实现进程同步?

Linux信号量是一种进程间同步机制,用于协调多个进程对共享资源的访问,通过P(wait,资源申请)和V(signal,资源释放)操作控制并发数量,避免竞争条件,在Python中,可通过高级接口multiprocessing.Semaphore和低级接口os模块的信号量系统调用来实现信号量的功能。

python 中如何用linux 信号量

Python中使用Linux信号量的两种方式

高级接口:multiprocessing.Semaphore

multiprocessing.Semaphore是Python标准库提供的基于进程池的信号量实现,适用于多进程编程场景,支持计数信号量(可指定初始值),其核心是通过acquire()方法获取资源(计数减1,若计数≤0则阻塞),通过release()方法释放资源(计数加1)。

示例:限制同时运行的进程数

from multiprocessing import Process, Semaphore
import time
def worker(sem, num):
    sem.acquire()  # P操作:获取资源
    print(f"进程 {num} 正在运行")
    time.sleep(2)  # 模拟耗时操作
    print(f"进程 {num} 结束")
    sem.release()  # V操作:释放资源
if __name__ == "__main__":
    sem = Semaphore(3)  # 初始值为3,最多3个进程同时运行
    processes = []
    for i in range(5):  # 创建5个进程
        p = Process(target=worker, args=(sem, i))
        processes.append(p)
        p.start()
    for p in processes:
        p.join()  # 等待所有进程结束

运行结果中,任意时刻最多只有3个进程同时打印运行信息,其余进程需等待release()后才能执行。

低级接口:os模块的信号量系统调用

os模块提供了直接操作Linux System V IPC信号量的接口,包括semget(创建/获取信号量集)、semop(执行P/V操作)、semctl(控制信号量集),适用于需要底层精细控制的场景。

python 中如何用linux 信号量

核心函数说明

  • semget(key, nsems, flags):创建或获取信号量集,key为唯一标识,nsems为信号量数量,flags包含IPC_CREAT(创建新信号量集)等。
  • semop(semid, sops):执行P/V操作,sops为操作数组,sem_op=-1为P操作(阻塞至资源可用),sem_op=1为V操作(释放资源)。
  • semctl(semid, semnum, cmd, ...):控制信号量集,如SETVAL(设置初始值)、IPC_RMID(删除信号量集)。

示例:用二值信号量保护文件写入

import os
import sys
from time import sleep
def process1(semid):
    semop(semid, [{'sem_num': 0, 'sem_op': -1, 'sem_flg': 0}])  # P操作
    with open("test.txt", "a") as f:
        f.write("进程1写入n")
    semop(semid, [{'sem_num': 0, 'sem_op': 1, 'sem_flg': 0}])  # V操作
def process2(semid):
    semop(semid, [{'sem_num': 0, 'sem_op': -1, 'sem_flg': 0}])
    with open("test.txt", "a") as f:
        f.write("进程2写入n")
    semop(semid, [{'sem_num': 0, 'sem_op': 1, 'sem_flg': 0}])
if __name__ == "__main__":
    key = 0x1234  # 信号量集唯一标识
    semid = os.semget(key, 1, 0666 | os.IPC_CREAT)  # 创建信号量集,1个信号量
    os.semctl(semid, 0, os.SETVAL, 1)  # 初始值为1(二值信号量)
    pid1 = os.fork()
    if pid1 == 0:
        process1(semid)
        sys.exit()
    pid2 = os.fork()
    if pid2 == 0:
        process2(semid)
        sys.exit()
    os.waitpid(pid1, 0)  # 等待子进程结束
    os.waitpid(pid2, 0)
    os.semctl(semid, 0, os.IPC_RMID)  # 删除信号量集

运行后,test.txt中进程1和进程2的写入内容会顺序出现,避免同时写入导致数据混乱。

两种方式对比

实现方式 核心模块 适用场景 操作方法 优点 缺点
高级接口 multiprocessing 进程同步,简单场景 acquire/release 简单易用,自动管理 依赖进程池,灵活性较低
低级接口 os 底层同步,复杂控制 semget/semop/semctl 灵活,直接控制IPC 复杂,需手动管理资源

相关问答FAQs

Q1: Python中multiprocessing.Semaphoreos模块的信号量有什么区别?
A1: multiprocessing.Semaphore是高级接口,基于进程池设计,适用于多进程编程,提供acquire/release方法,自动管理信号量生命周期,适合简单同步场景;os模块信号量是低级接口,直接操作System V IPC,需手动创建、操作和删除信号量集,灵活性高但复杂,适用于需要精细控制的底层同步。

python 中如何用linux 信号量

Q2: 信号量与互斥锁(Lock)的区别是什么?
A2: 信号量(Semaphore)是计数同步机制,允许多个进程同时访问资源(计数>1时),适用于资源池控制(如限制数据库连接数);互斥锁(Lock)是二值信号量(计数仅0或1),只允许一个进程访问资源,适用于互斥访问(如保护共享变量),信号量更灵活,可控制并发数;互斥锁更简单,专注于互斥场景。

原创文章,发布者:酷番叔,转转请注明出处:https://cloud.kd.cn/ask/15642.html

(0)
酷番叔酷番叔
上一篇 2025年8月24日 01:55
下一篇 2025年8月24日 02:06

相关推荐

  • Linux文件权限怎么查看?

    使用 ls -l 命令(最常用)命令示例:ls -l 文件名 # 查看单个文件ls -l # 查看当前目录所有文件权限ls -ld 目录名 # 查看目录本身权限(而非内容)输出示例:-rwxr-xr– 1 user group 4096 Jan 10 15:30 example.txt权限字段解析(共10个字……

    2025年7月9日
    5100
  • Linux重复上条命令只会用上箭头?

    最常用方法: 命令原理: 会自动替换为历史记录中的上一条命令,操作示例:$ apt update # 首次执行$ sudo !! # 重复执行 → 实际运行 sudo apt update适用场景:需添加权限(如 sudo)或快速重试命令,方向键回溯:(向上键)操作步骤:按键盘 键调出上一条命令按 Enter……

    2025年7月29日
    4100
  • Linux终端中查看文件时如何实现翻页操作?

    在Linux操作系统中,翻页操作是日常使用中非常频繁的需求,无论是查看长文本文件、浏览命令输出结果,还是阅读日志信息,掌握翻页技巧都能显著提升操作效率,Linux中的翻页操作主要涉及命令行工具、文本编辑器以及终端模拟器自带功能,下面将从多个场景详细说明具体实现方法,使用less和more分页查看输出在Linux……

    2025年9月23日
    1800
  • 电脑卡顿?这个方法能解决吗

    在Linux开发环境中,-lm是编译C/C++程序时链接数学库(libm.so)的关键选项,数学库提供了基础的数学函数(如三角函数、对数、幂运算等),默认情况下GCC不会自动链接该库,需手动添加,以下是详细使用指南:为什么需要 -lm?Linux的数学函数(如sin(), sqrt(), pow())定义在li……

    2025年7月15日
    5300
  • 如何快速拓展人脉?

    访问前的准备工作确保 MySQL 服务已运行 sudo systemctl status mysql # 检查服务状态sudo systemctl start mysql # 若未运行则启动服务获取有效账户信息需准备 MySQL 用户名和密码(默认管理员账户为 root),新安装的 MySQL 可通过临时密码登……

    2025年6月27日
    5100

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

400-880-8834

在线咨询: QQ交谈

邮件:HI@E.KD.CN

关注微信