1 多线程是什么?

1.1 多线程的概念?

说起多线程,那么就不得不说什么是线程,而说起线程,又不得不说什么是进程。

进程可以简单的理解为一个可以独立运行的程序单位,它是线程的集合,进程就是有一个或多个线程构成的。而线程是进程中的实际运行单位,是操作系统进行运算调度的最小单位。可理解为线程是进程中的一个最小运行单元。

那么多线程就很容易理解:多线程就是指一个进程中同时有多个线程正在执行。

为什么要使用多线程?

  • 在一个程序中,有很多的操作是非常耗时的,如数据库读写操作,IO操作等,如果使用单线程,那么程序就必须等待这些操作执行完成之后才能执行其他操作。使用多线程,可以在将耗时任务放在后台继续执行的同时,同时执行其他操作。

  • 可以提高程序的效率。

  • 在一些等待的任务上,如用户输入,文件读取等,多线程就非常有用了。

缺点:

  • 使用太多线程,是很耗系统资源,因为线程需要开辟内存。更多线程需要更多内存。

  • 影响系统性能,因为操作系统需要在线程之间来回切换。

  • 需要考虑线程操作对程序的影响,如线程挂起,中止等操作对程序的影响。

  • 线程使用不当会发生很多问题。

总结:多线程是异步的,但这不代表多线程真的是几个线程是在同时进行,实际上是系统不断地在各个线程之间来回的切换(因为系统切换的速度非常的快,所以给我们在同时运行的错觉)。

 

1.2 并行、并发、高并发等概念

并行:多个CPU实例或多台机器同时执行一段处理逻辑,是真正的同时。

并发:通过CPU调度算法,让用户看上去同时执行,实际上CPU操作层面不是真正的同时。

并发时如果操作了公用资源,可能产生线程安全问题。

线程安全:多个线程操作公用资源,有可能产生安全问题。

高并发:高并发指的是是一种系统运行过程中遇到的一种“短时间内遇到大量操作请求”的情况,主要发生在web系统集中大量访问或者socket端口集中性收到大量请求(例如:12306的抢票情况;天猫双十一活动)。该情况的发生会导致系统在这段时间内执行大量操作,例如对资源的请求,数据库的操作等。如果高并发处理不好,不仅仅降低了用户的体验度(请求响应时间过长),同时可能导致系统宕机,严重的甚至导致OOM异常,系统停止工作等。如果要想系统能够适应高并发状态,则需要从各个方面进行系统优化,包括,硬件、网络、系统架构、开发语言的选取、数据结构的运用、算法优化、数据库优化……。

1.3 多线程与高并发的联系。

多线程只是在同/异步角度上解决高并发问题的其中的一个方法手段,是在同一时刻利用计算机闲置资源的一种方式。

多线程在高并发问题中的作用就是充分利用计算机资源,使计算机的资源在每一时刻都能达到最大的利用率,不至于浪费计算机资源使其闲置。

2 多线程与多进程,选择谁?

下面是本人从知乎-pansz上转载的一个答案,非常通俗地回答了这个问题。

  • 单进程单线程:一个人在一个桌子上吃菜。

  • 单进程多线程:多个人在同一个桌子上一起吃菜。

  • 多进程单线程:多个人每个人在自己的桌子上吃菜。

多线程的问题是多个人同时吃一道菜的时候容易发生争抢,例如两个人同时夹一个菜,一个人刚伸出筷子,结果伸到的时候已经被夹走菜了。。。此时就必须等一个人夹一口之后,在还给另外一个人夹菜,也就是说资源共享就会发生冲突争抢。

1。对于 Windows 系统来说,【开桌子】的开销很大,因此 Windows 鼓励大家在一个桌子上吃菜。因此 Windows 多线程学习重点是要大量面对资源争抢与同步方面的问题。

2。对于 Linux 系统来说,【开桌子】的开销很小,因此 Linux 鼓励大家尽量每个人都开自己的桌子吃菜。这带来新的问题是:坐在两张不同的桌子上,说话不方便。因此,Linux 下的学习重点大家要学习进程间通讯的方法。

开桌子的意思是指创建进程。开销这里主要指的是时间开销。
可以做个实验:创建一个进程,在进程中往内存写若干数据,然后读出该数据,然后退出。此过程重复 1000 次,相当于创建/销毁进程 1000 次。在我机器上的测试结果是:
UbuntuLinux:耗时 0.8 秒
Windows7:耗时 79.8 秒
两者开销大约相差一百倍。
这意味着,在 Windows 中,进程创建的开销不容忽视。换句话说就是,Windows 编程中不建议你创建进程,如果你的程序架构需要大量创建进程,那么最好是切换到 Linux 系统。

大量创建进程的典型例子有两个,一个是 gnu autotools 工具链,用于编译很多开源代码的,他们在 Windows 下编译速度会很慢,因此软件开发人员最好是避免使用 Windows。另一个是服务器,某些服务器框架依靠大量创建进程来干活,甚至是对每个用户请求就创建一个进程,这些服务器在 Windows 下运行的效率就会很差。这"可能"也是放眼全世界范围,Linux 服务器远远多于 Windows 服务器的原因。

再次补充:如果你是写服务器端应用的,其实在现在的网络服务模型下,开桌子的开销是可以忽略不计的,因为现在一般流行的是按照 CPU 核心数量开进程或者线程,开完之后在数量上一直保持,进程与线程内部使用协程或者异步通信来处理多个并发连接,因而开进程与开线程的开销可以忽略了。
另外一种新的开销被提上日程:核心切换开销。
现代的体系,一般 CPU 会有多个核心,而多个核心可以同时运行多个不同的线程或者进程。当每个 CPU 核心运行一个进程的时候,由于每个进程的资源都独立,所以 CPU 核心之间切换的时候无需考虑上下文。
当每个 CPU 核心运行一个线程的时候,由于每个线程需要共享资源,所以这些资源必须从 CPU 的一个核心被复制到另外一个核心,才能继续运算,这占用了额外的开销。换句话说,在 CPU 为多核的情况下,多线程在性能上不如多进程。
因而,当前面向多核的服务器端编程中,需要习惯多进程而非多线程。

参考:

汪同学

最新文章

  1. 关于EventSource的精华
  2. CentOS 6.3下Samba服务器的安装与配置
  3. jQuery操作json数据
  4. Get_File_Name Usage in Oracle Forms 6i
  5. Intro to Filtering with Network Monitor 3.0
  6. 腾讯云 安全组配置及与MySQL 远程登录失败原因浅析
  7. ssh 内在溢出
  8. OC - 正则表达式 - RegexKitLite
  9. JAVA9模块化详解(一)——模块化的定义
  10. c++中的类之构造函数
  11. 项目中BigDecimal与Double使用场景
  12. FFmpeg的H.264解码器源代码简单分析:熵解码(Entropy Decoding)部分
  13. 使用Redis构建全局并发锁
  14. 7.4 electirc.c -- 计算电费
  15. NaviSoft31.源码开发完成
  16. Android SDK Content loader has encountered a problem” “parseSdkContent Failed ”
  17. linux proc目录介绍
  18. 【转】MEF程序设计指南五:迟延(Lazy)加载导出部件(Export Part)与元数据(Metadata)
  19. 20145203 实验五 Java网络编程及安全
  20. Xshell和Xftp5配置连接阿里云服务器

热门文章

  1. [HDU1576] A/B(扩展欧几里得)
  2. 在workbench中导入.sql文件!(导入数据库文件)
  3. android开发里跳过的坑——android studio升级完成后eclipse adt无法正常使用
  4. [转]如何阅读android framework源码
  5. 【ZJOI2018 Round2游记】
  6. hdu - 1150 Machine Schedule (二分图匹配最小点覆盖)
  7. [bzoj2738]矩阵乘法_整体二分_树状数组
  8. 爱普生L201
  9. 数据库可视化操纵软件有navicat和sqlyog
  10. SAS编程基础 - 菜鸟入门常用操作