0

0

c# Barrier 和 CountdownEvent 的区别 c#多线程同步

畫卷琴夢

畫卷琴夢

发布时间:2026-01-26 06:53:30

|

772人浏览过

|

来源于php中文网

原创

Barrier适合多阶段协同,CountdownEvent仅等待N个独立操作完成;前者支持阶段回调、可重用、需SignalAndWait()同步进入下一阶段,后者无回调、归零后需Reset()才能复用。

c# barrier 和 countdownevent 的区别 c#多线程同步

Barrier 适合多阶段协同,CountdownEvent 只管“全部做完”

根本区别在于同步意图:Barrier 是为「分阶段并行」设计的,比如多个线程一起执行 Phase 1 → 全部到达后自动进入 Phase 2;而 CountdownEvent 是为「等待 N 个独立操作完成」设计的,它不关心阶段、不回调、不重用(除非手动 Reset()),只等计数归零就放行。

  • Barrier 构造时指定参与者数量,每次调用 SignalAndWait() 表示“我这阶段干完了,等别人”,全员到齐才继续下一阶段
  • CountdownEvent 构造时传入初始计数(如 new CountdownEvent(5)),每个任务结束调一次 Signal(),仅此而已
  • Barrier 支持阶段回调(构造时传 Action),CountdownEvent 完全没有回调机制
  • Barrier 可重用(每阶段自动递增 CurrentPhaseNumber),CountdownEvent 一旦归零就进入就绪态,再 Wait() 不阻塞——必须显式 Reset(n) 才能复用

Signal() 和 SignalAndWait() 的语义完全不同

别被名字误导:CountdownEvent.Signal() 就是简单减一;而 Barrier.SignalAndWait() 是原子操作:先发信号 + 立即阻塞,直到所有其他参与者也调了 SignalAndWait()

  • CountdownEvent.Signal() 可在任意位置安全调用(推荐放在 finally 块里防异常漏调)
  • Barrier.SignalAndWait() 必须成对出现在每个参与者的同一逻辑点,否则会死锁——比如一个线程在 Phase 1 调了,另一个却跳过直接进 Phase 2,前者永远卡住
  • Barrier 还提供带超时的 SignalAndWait(int timeout),返回 false 表示有人没按时到达;CountdownEvent.Wait() 也有超时重载,但意义不同:只是防止无限等待

常见误用:把 CountdownEvent 当 Barrier 用

典型错误是想实现“所有线程做完第一件事,再一起做第二件事”,却只用 CountdownEvent ——它无法保证“同时出发”。你只能靠两次 Wait() + 两次 Reset() 模拟,但中间存在竞态:部分线程可能已开始第二件事,而另一些还在重置计数器。

Meituan CatPaw
Meituan CatPaw

美团推出的智能AI编程Agent

下载
  • 正确做法:用 Barrier,天然支持多阶段同步,且 SignalAndWait() 保证所有线程在阶段边界严格对齐
  • 如果硬要用 CountdownEvent 模拟两阶段,必须加额外同步(如 ManualResetEventSlim 控制第二阶段启动),代码变复杂且易出错
  • CountdownEvent 更适合场景:启动 10 个 HTTP 请求,主线程等全部响应返回再汇总;或异步文件写入,等所有 FileStream.WriteAsync 完成再关闭

Dispose() 和线程安全注意事项

两者都需显式释放资源,但风险点不同。

  • CountdownEvent.Dispose() 后再调 Wait()Signal() 会抛 ObjectDisposedException;若不确定是否已释放,可用 TryAddCount() 替代 AddCount() 避免异常
  • Barrier.Dispose() 后再调 SignalAndWait() 同样报错;但它还要求所有参与者必须在 Dispose() 前退出同步点,否则可能引发未定义行为
  • 两者所有成员方法都是线程安全的,无需额外加锁;但 CountdownEvent.Reset()Barrier 的构造/销毁不能和活跃的 Signal* 操作并发
static void Example_CountdownEvent()
{
    using var countdown = new CountdownEvent(2);
    _ = Task.Run(() => { Thread.Sleep(1000); Console.WriteLine("Task1 done"); countdown.Signal(); });
    _ = Task.Run(() => { Thread.Sleep(1500); Console.WriteLine("Task2 done"); countdown.Signal(); });
    countdown.Wait(); // 主线程阻塞至此
    Console.WriteLine("All done");
}

static void Example_Barrier()
{
    using var barrier = new Barrier(2, b => Console.WriteLine($"Phase {b.CurrentPhaseNumber} ended"));
    _ = Task.Run(() =>
    {
        Console.WriteLine("Phase1 step1");
        barrier.SignalAndWait();
        Console.WriteLine("Phase2 step1");
        barrier.SignalAndWait();
    });
    _ = Task.Run(() =>
    {
        Console.WriteLine("Phase1 step2");
        barrier.SignalAndWait();
        Console.WriteLine("Phase2 step2");
        barrier.SignalAndWait();
    });
}
最常被忽略的一点:不要在 Barrier 的回调(postPhaseAction)里做耗时操作,它会阻塞所有等待线程——这个回调是在最后一个到达者线程上下文中同步执行的。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

401

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

543

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

53

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

197

2025.08.29

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

482

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

144

2025.12.24

java多线程相关教程合集
java多线程相关教程合集

本专题整合了java多线程相关教程,阅读专题下面的文章了解更多详细内容。

5

2026.01.21

C++多线程相关合集
C++多线程相关合集

本专题整合了C++多线程相关教程,阅读专题下面的的文章了解更多详细内容。

11

2026.01.21

c++ 根号
c++ 根号

本专题整合了c++根号相关教程,阅读专题下面的文章了解更多详细内容。

70

2026.01.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号