Karp 的技术博客

在并发编程中,栅栏(Barrier)信号量(Semaphore) 是两种重要的同步原语,常用于协调多个线程或进程之间的执行顺序或资源访问。下面是它们的概念、区别、使用场景对比:


🚧 一、信号量(Semaphore)

🔹 概念:

信号量是一种计数器机制,用来控制多个线程对共享资源的访问。

  • 有两种主要类型:

    • 计数信号量:可以有多个许可,常用于控制并发访问数量
    • 二元信号量(Binary Semaphore):许可只有 0 和 1,用于实现互斥锁的功能

🔹 用法(伪代码):

Semaphore sem = new Semaphore(3);  // 最多允许3个线程同时访问资源

sem.acquire();   // 获取许可,若无则阻塞等待
// 访问资源
sem.release();   // 释放许可

✅ 使用场景:

  • 数据库连接池(控制最大连接数)
  • 限制 API 并发请求数量
  • 控制资源访问(例如:只允许 n 个线程同时写文件)

🧱 二、栅栏(Barrier)

🔹 概念:

栅栏是一种阶段性同步机制,用于让多个线程(或任务)在某个“关口”等待,直到所有线程都到达栅栏后,才统一继续执行

🔹 用法(伪代码):

barrier = threading.Barrier(3)

def worker():
    # 做一些任务
    barrier.wait()  # 等待其他线程到达
    # 所有线程到达后同时继续

✅ 使用场景:

  • 多线程并行计算,每个线程处理一部分数据,最后一起合并结果
  • 分布式任务阶段同步,如 MapReduce 中的 Map 阶段结束后统一进入 Reduce

🔍 三、栅栏 vs 信号量:对比总结

特性信号量(Semaphore)栅栏(Barrier)
本质计数器同步点
控制资源访问✅ 是❌ 否
用于阶段性同步❌ 否✅ 是
是否可重用✅ 可以✅ 通常可重用
适合场景控制并发数、访问控制线程协作、阶段同步
实现复杂度较低中等

✅ 示例场景

信号量应用:

限制同时访问数据库的线程数:

semaphore = threading.Semaphore(10)

def db_access():
    semaphore.acquire()
    try:
        access_db()
    finally:
        semaphore.release()

栅栏应用:

等待所有线程准备好再执行下一步任务:

barrier = threading.Barrier(5)

def step_work():
    prepare_data()
    barrier.wait()
    start_main_task()

版权属于:karp
作品采用:本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
更新于: 2025年06月11日 12:58
0

目录

来自 《并发编程 栅栏 (Barrier) 和 信号量 (Semaphore)》