关于阻碍并发容器纳入ISO C++标准的具体技术障碍的正式问询
你问到点子上了——把成熟的并发容器纳入C++标准确实是个看似顺理成章,实则充满技术博弈与妥协难题的事儿,之前几个相关提案折戟沉沙,核心就是卡在了下面这些具体的硬骨头里:
性能与硬件架构的强绑定矛盾
不同CPU架构的内存模型、原子指令集差异极大:x86采用的是TSO(总存储顺序)内存模型,原子操作的语义相对简单;而ARM、RISC-V这类弱内存模型的架构,需要额外的内存屏障指令才能保证操作的可见性。要设计一个在所有架构上都能保持高效的并发容器几乎是个“不可能三角”——偏向某类架构优化,就会牺牲另一类架构的性能,而标准必须做到完全可移植,这让性能调优的空间被极度压缩。接口设计的易用性与灵活性两难
标准库的接口需要同时兼顾新手的“开箱即用”和专家的“深度定制”需求。如果把并发容器的同步逻辑完全封装死,新手用起来简单,但专家会失去自定义锁策略、内存分配器并发安全配置这类关键灵活性;但如果接口设计得过于灵活,又会让普通开发者望而却步,违背标准库降低使用门槛的初衷。之前的几个提案正是在接口的权衡上没能达成广泛共识。并发语义的精确标准化难度
并发场景下的行为语义要做到精确无歧义太难了:比如多线程同时插入、删除时,迭代器的有效性该怎么定义?是允许迭代器在并发修改时立即失效,还是要保证某种弱一致性?不同的业务场景需要不同的语义,但标准必须给出唯一、明确的规则,这需要协调覆盖几乎所有可能的使用场景,很难让所有委员会成员和用户群体都满意。与现有容器生态的兼容性冲突
标准库不能脱离现有生态独立设计。比如要把std::unordered_map扩展为并发版本,要不要保持和非并发容器一致的接口?但像operator[]这类非并发容器的常用接口,在并发场景下语义会完全改变——单线程里它是“查找或插入”,但多线程下直接复用会引发竞态条件,甚至导致数据损坏。强行兼容现有接口可能会误导用户写出不安全的代码,重新设计接口又会打破用户的使用习惯。测试与验证的极高复杂度
并发程序的测试本身就是世界级难题,要覆盖所有可能的线程调度顺序、竞态条件几乎不可能。而标准库的组件需要经过极端严格的验证,确保在所有合规编译器和硬件平台上都能稳定工作。并发容器的测试案例数量是单线程容器的指数级增长,验证成本高到难以想象,委员会必须确保每一个细节都没有漏洞,这需要消耗大量的时间和资源。
确实,标准化的并发容器能让C++开发者不用依赖第三方库,就能写出更安全的多线程代码,但这些技术障碍不是一朝一夕能解决的,需要在性能、易用性、可移植性之间找到一个所有人都能接受的平衡点。
内容来源于stack exchange

