# procsroutines **Repository Path**: graviton/procsroutines ## Basic Information - **Project Name**: procsroutines - **Description**: Process, threadings, routines - **Primary Language**: Unknown - **License**: AGPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-28 - **Last Updated**: 2026-09-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # procsroutines 一个用短小、可运行的例子学习 Python 线程同步的项目。示例集中在 [`src/procsroutines/threading_demo.py`](src/procsroutines/threading_demo.py),需要 Python 3.13+ 和 `uv`。 ## 运行 ```powershell uv sync uv run procsroutines # 运行全部示例 uv run procsroutines condition # 运行指定示例 uv run procsroutines portalocker # 在 Windows 上演示文件锁 uv run python -m procsroutines.threading_demo barrier ``` 命令打印每个示例的结果,例如 `lock` 的计数器应为 `4000`,`semaphore` 的 `maximum_active` 不超过 `2`,`portalocker` 的 `maximum_active` 应为 `1`。 线程调度顺序不固定,不应依赖各线程的运行先后。 ## 核心区别 | 原语 | 用途 | 关键行为 | | --- | --- | --- | | `Lock` | 保护共享数据 | 同时只能有一个持有者;同一线程再次获取会阻塞 | | `RLock` | 嵌套调用需要同一把锁 | 同一线程可重复获取,必须对应次数释放 | | `Condition` | 等待共享状态满足条件 | `wait()` 暂时释放绑定的锁,醒来后重新获取;始终循环检查条件 | | `Semaphore` | 限制同时使用资源的数量 | 许可证计数允许最多 N 个线程同时进入 | | `Event` | 通知一个状态已发生 | `set()` 唤醒所有等待者,状态保持为真直到 `clear()` | | `Timer` | 延迟调用一次函数 | 启动一个定时线程;执行前可以 `cancel()` | | `Barrier` | 多个线程在阶段边界汇合 | 等指定数量的线程全部到达后一起继续 | | `fcntl.flock` | Unix 文件锁 | 对独立打开的文件句柄加锁;只对遵守锁协议的访问方有效 | | `portalocker` | 跨平台文件锁 | 在 Windows 和 Unix 上使用原生文件锁 API,锁定实际文件 | `Lock` 和 `RLock` 用于进程内的线程互斥;文件锁可用于约定好的跨进程文件访问。 本项目的两个文件锁示例仍使用线程演示竞争,每个线程独立打开同一个文件。 `Condition`、`Event` 和 `Barrier` 解决的是等待与通知问题,不能代替共享数据的互斥保护。 ## Windows 文件锁 Python 标准库的 `fcntl.flock` 只在 Unix 系统可用。在 Windows 运行 `uv run procsroutines flock` 会打印 `supported: False`,不会尝试模拟 `flock`。 项目依赖 `portalocker`,因此 `uv run procsroutines portalocker` 可在 Windows 运行。 另一种轻量选择是 `filelock`:它通常锁单独的 `.lock` 文件,适合所有参与者约定使用同一锁文件的场景。 Windows 标准库也提供 `msvcrt.locking`,但它的接口与 `flock` 不同。 ## 使用提示 - 对共享可变数据,明确界定临界区,并尽量用 `with` 确保释放锁。 - `Condition.wait()` 返回后重新检查谓词;`notify()` 不会替等待者直接释放锁。 - `Barrier` 可能因超时或参与线程失败而抛出 `BrokenBarrierError`。 - `threading` 适合 I/O 并发;CPU 密集型任务的并行效果取决于 Python 实现与是否启用 free-threaded 构建。