zl程序教程

您现在的位置是:首页 >  后端

当前栏目

为什么多线程是个坏主意

多线程 为什么
2023-09-11 14:16:09 时间

在 Unix编程艺术 中,提到了尽量避免多线程编程模型, 认为这样只会增加复杂度, 提倡使用多进程, 这样本质上就可以避免多线程『共享内存数据』产生的 “corruotped memory” 问题。

其中, 提到了一篇文章 Why Threads Are A Bad Idea, 对于多线程编程和事件编程分析的非常好, 具体的翻译如下:

线程的背景: 在操作系统中出现多线程 逐渐演变成 用户层面的编程工具 被认为是多种问题的一种通用解决方案 每一个程序员都需要成为 一个多线程编程的高手吗? 根本性的问题:

多线程的程序非常难以正确的编写!!!

替代性的方案:

使用事件驱动的编程方法

特别声明: 对于大部分的多线程程序,使用事件驱动是一个更好的选择 只有当使用CPU多核的时候, 才需要使用多线程编程 2 多线程的本质

多线程编程

一般用来管理并发问题 多个独立相互执行的任务 共享的内存 预先的安排机制(Pre-emptive scheduling) 同步机制(synchronization) 3 多线程的用途 操作系统: 对每一个用户进程分配一个内核线程 科学应用程序: 每个CPU分配一个线程(对计算要求性很高的程序) 分布式系统: 进程请求并行(同步记性的I/O操作) GUIs程序 线程对应用户的行为. 在长时间的后台计算过程中仍然可以处理图形展示 多媒体, 动画方面的程序编写
4 多线程有什么问题?

痛苦指数

对于一般的程序员而言,难以掌握。 即使对于专家,多线程编程也是痛苦的。 5 为什么多线程编程很难? Synchronization(同步机制): 必须通过锁来共享数据 忘记了加锁?就会导致受污染的数据

系统挂起

6 为什么多线程编程很难? 难以调试: 因为 数据依赖,时间依赖 线程破坏了抽象: 无法设计出模块化的程序 因为锁导致回调无法完成

多线程

7 为什么多线程编程很难? 很难达到非常好的性能 简单的锁导致了低并发 而精密的锁又会导致复杂度提升, 降低了一般情况下的性能 OSes限制了性能提升(调度, 环境切换)

事件驱动

9 事件驱动编程被用来干什么 大多数的GUIs编程: 一个处理器对应一个事件 处理器用来执行行为(撤销,删除文件等)
对于长时间运行的程序Fork off子程序处理, 当处理结束后使用事件 打断处理器执行(比如: 事件驱动的I/O) 定期回调 时间处理器中的 事件循环
使用事件驱动编程更加容易: 不用考虑并发, 不用考虑抢占, 不用考虑同步和死锁 只在特定的情况下,才使用复杂的技术栈 使用多线程编程, 即使最简单的程序也需要面对很高的复杂度(full complexity)
事件驱动编程只和时间依赖有关, 不需要考虑内部的调度 问题更加容易跟踪: 较慢的按钮点击反应 和 内存数据污染 时候, 前者问题更加容易定位
对于 GUIs程序, 分布式系统, 性能要求不高的, 使用事件编程, 不是多线程 只有当真正的多核CPU并发需要使用到的时候,使用多线程编程 当使用多线程编程的时候,将多线程编程模块与其他模块进行隔离, 保持大部分代码都是单线程模型