CP.1: Assume that your code will run as part of a multi-threaded program

CP.1: 设想你的代码会成为多线程程序的一部分

Reason(原因)

It's hard to be certain that concurrency isn't used now or won't be used sometime in the future. Code gets reused. Libraries not using threads may be used from some other part of a program that does use threads. Note that this rule applies most urgently to library code and least urgently to stand-alone applications. However, over time, code fragments can turn up in unexpected places.

很难确定现在不需要并发或者将来的某个时间也不会使用。代码会被重用的。没有使用线程的库有可能被使用线程的、程序的其它部分使用。注意本准则对于功能库具有最大的紧迫性,而对于单独的应用程序就没什么紧迫性。然而,随着时间的推移,代码片段会出现在意想不到的地方。

Example, bad(反面示例)

double cached_computation(double x)
{// bad: these statics cause data races in multi-threaded usagestatic double cached_x = 0.0;static double cached_result = COMPUTATION_OF_ZERO;if (cached_x != x) {cached_x = x;cached_result = computation(x);}return cached_result;
}

Although cached_computation works perfectly in a single-threaded environment, in a multi-threaded environment the two static variables result in data races and thus undefined behavior.

虽然缓存计算可以在单线程环境中运行得很完美,但在多线程环境中,两个静态变量处于数据竞争状态,因此会导致无定义的行为。

Example, good(范例)

struct ComputationCache {    double cached_x = 0.0;    double cached_result = COMPUTATION_OF_ZERO;
    double compute(double x) {        if (cached_x != x) {            cached_x = x;            cached_result = computation(x);        }        return cached_result;    }};

Here the cache is stored as member data of a ComputationCache object, rather than as shared static state. This refactoring essentially delegates the concern upward to the caller: a single-threaded program might still choose to have one global ComputationCache, while a multi-threaded program might have one ComputationCache instance per thread, or one per "context" for any definition of "context." The refactored function no longer attempts to manage the allocation of cached_x. In that sense, this is an application of the Single Responsibility Principle.

这段代码中,缓存数据存作为ComputationCache对象的数据成员存储,而不是静态的状态数据。这个重构从根本上将决定权向上委托给调用者:单线程程序可以继续使用全局的ComputationCache实例,而多线程程序可以每个线程管理一个ComputationCache实例,或者每个上下文一个实例,这个上下文可以有多种解释。重构的函数不再试图管理cached_x的内存分配。从这个角度来讲,这算是单独责任原则的一个应用。

In this specific example, refactoring for thread-safety also improved reusability in single-threaded programs. It's not hard to imagine that a single-threaded program might want two ComputationCache instances for use in different parts of the program, without having them overwrite each other's cached data.

在这个特定的例子中,目的在于线程安全的重构同时提高了单线程环境中的重用性。不难想象单线程有可能需要两个用于程序不同部分的ComputationCache实例,而不会发生缓存数据的相互覆盖。

There are several other ways one might add thread-safety to code written for a standard multi-threaded environment (that is, one where the only form of concurrency is std::thread):

存在很多其他的方式,其中一个是为了在标准的多线程环境(即,使用并发的唯一形式std::thread)中运行的代码中增加线程安全处理。

  • Mark the state variables as thread_local instead of static.

  • 将状态变量定义为线程内部的局部变量而不是静态变量。

  • Implement concurrency control, for example, protecting access to the two static variables with a static std::mutex.

  • 实现并发控制,例如,使用静态的std::mutex保护对两个静态变量的访问。

  • Refuse to build and/or run in a multi-threaded environment.

  • 拒绝在多任务环境中编译或执行代码。

  • Provide two implementations: one for single-threaded environments and another for multi-threaded environments.

  • 提供两种实现:一个用于单线程环境,另一个用于多线程环境。

Exception(例外)

Code that is never run in a multi-threaded environment.

永远不会运行于多线程环境的代码。

Be careful: there are many examples where code that was "known" to never run in a multi-threaded program was run as part of a multi-threaded program, often years later. Typically, such programs lead to a painful effort to remove data races. Therefore, code that is never intended to run in a multi-threaded environment should be clearly labeled as such and ideally come with compile or run-time enforcement mechanisms to catch those usage bugs early.

需要小心的是:存在很多事例本来被认为永远不会运行于多线程程序的代码最后成为多线程程序的一部分,通常是几年之后。一般来讲,为这样的程序消除数据竞争会非常痛苦。因此,一旦决定代码永远不会在多线程环境中运行,应该清晰地标记出来,而且最好同时提供编译和运行时的强制机制以尽早捕捉错误的用法。

原文链接

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#cp1-assume-that-your-code-will-run-as-part-of-a-multi-threaded-program


新书介绍

以下是本人3月份出版的新书,拜托多多关注!

本书利用Python 的标准GUI 工具包tkinter,通过可执行的示例对23 个设计模式逐个进行说明。这样一方面可以使读者了解真实的软件开发工作中每个设计模式的运用场景和想要解决的问题;另一方面通过对这些问题的解决过程进行说明,让读者明白在编写代码时如何判断使用设计模式的利弊,并合理运用设计模式。

对设计模式感兴趣而且希望随学随用的读者通过本书可以快速跨越从理解到运用的门槛;希望学习Python GUI 编程的读者可以将本书中的示例作为设计和开发的参考;使用Python 语言进行图像分析、数据处理工作的读者可以直接以本书中的示例为基础,迅速构建自己的系统架构。

觉得本文有帮助?欢迎点赞并分享给更多的人。

更新文章,请关注微信公众号【面向对象思考】

C++核心准则CP.1: 设想你的代码​会成为多线程程序的一部分相关推荐

  1. C++核心准则CP.26:不要分离线程

    CP.26: Don't detach() a thread CP.26:不要分离线程 Reason(原因) Often, the need to outlive the scope of its c ...

  2. php 语法 条件变量,C ++核心准则:注意条件变量的陷阱

    今天,我写了一篇关于条件变量的恐怖文章.您应该意识到条件变量的这一问题.C ++核心准则CP 42仅声明:"不要无条件等待". 等待!条件变量支持一个非常简单的概念.一个线程准备一 ...

  3. modbus软件开发实战指南_C++核心准则?GSL:指南支持库

    GSL: Guidelines support library GSL:指南支持库 The GSL is a small library of facilities designed to suppo ...

  4. 开源压缩算法brotli_Google的Brotli压缩算法,C ++核心准则以及更多新闻

    开源压缩算法brotli 在本周的开源新闻综述中,我们将介绍Google的Brotli压缩算法,适用于GitHub的Classroom,C ++ Core Guidelines等! 2015年9月20 ...

  5. 02 线程简介 多任务 多线程 普通方法调用和多线程 程序.进程.线程 Proces与Thread 核心概念

    线程简介 任务,进程,线程,多线程 多任务 多任务处理是指用户可以在同一时间内运行多个应用程序,每个应用程序被称作一个任务 多线程 原来是一条路,慢慢因为车太多了,道路堵塞,效率极低. 为了提高使用的 ...

  6. C++核心准则C.4:只有直接访问表达的函数,才应该成为成员

    C.4: Make a function a member only if it needs direct access to the representation of a class C.4:只有 ...

  7. C++核心准则ES.56​:只在需要将一个对象显式移动到另外的作用域时使用std::move​

    ES.56: Write std::move() only when you need to explicitly move an object to another scope ES.56:只在需要 ...

  8. C++核心准则边译边学-目标之外

    In.not: Non-aims(目标之外) The rules are not intended to be minimal or orthogonal. In particular, genera ...

  9. C++核心准则ES.40:避免复杂的表达式

    ES.40: Avoid complicated expressions ES.40:避免复杂的表达式 Reason(原因) Complicated expressions are error-pro ...

最新文章

  1. 数据库的设计经验(经典)
  2. 函数式思维: 利用 Either 和 Option 进行函数式错误处理 类型安全的函数式异常...
  3. QString::QString 中文乱码
  4. 20175204 张湲祯 2018-2019-2《Java程序设计》第九周学习总结
  5. php如何拼接变量名,php动态拼接变量名,可变变量,动态变量,使用花括号,使用两个$符...
  6. Web工程师修行笔记_必备单词(第三部)
  7. Android菜鸟如何学习Android系统开发?
  8. 以相关组为基础的3D物体识别
  9. python需要花钱下载吗_用Python下载知乎视频,非常实用
  10. simulink中if模块_Simulink与圈复杂度
  11. 初次注册使用Tushare Pro报错问题
  12. jQuery基础集锦——插件开发
  13. 【游戏体验】Colour My World(让我的世界充满色彩)
  14. 小米路由器的linux命令,小米路由器pro安装mt工具箱
  15. RDPWrap1.6.2让windows家庭版Home实现远程桌面
  16. 苹果cms播放器html,解决苹果cmsv10版本ckplayer播放器高度自适应兼容问题
  17. vscode下载与安装,解决安装包下载慢问题
  18. “囍”博物馆与Interesting 有点意思
  19. spyder pyecharts不显示_微星PAG272QRZ显示器好不好用 微星PAG272QRZ显示器全面评测_显示器_硬件教程...
  20. 恢复出厂设置android手机号码,手机怎么恢复出厂设置 安卓手机恢复出厂设置方法汇总...

热门文章

  1. 解决 此更新不适用于你的计算机 安装msu文件时的错误提示
  2. 大洋云服务器_网易云音乐TFBOYS线上演唱会破纪录,观看体验不输线下
  3. Mac OS : Homebrew安装,配置maven 环境变量 / FORMULA(命令行) | CASK(图形化界面)
  4. 生活中的网络必备常识,2.4G和5GWIFI信号频率,你真的了解吗
  5. margin collapsing现象
  6. 【知识图谱】命名实体识别(NLP)
  7. vue项目低版本浏览器XP/IE适配方案
  8. 【算法学习笔记】van Emde Boas树
  9. RN新手上路-----底部导航栏图标设置
  10. dede 分页 上一页 下一页