前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java 并发编程(一):摩拳擦掌

Java 并发编程(一):摩拳擦掌

作者头像
沉默王二
发布2019-08-30 14:59:23
4160
发布2019-08-30 14:59:23
举报
文章被收录于专栏:沉默王二

01、为什么需要操作系统

我喜欢在写文章(不用纸和笔用电脑了)的时候听音乐(不用 MP3 用电脑了),假如电脑只能做一件事情的话,我就只能在写完文章的时候再听音乐,或者听完音乐的时候再开始写作,这样就很不爽——在没有操作系统前,的确就是这么不爽。

有了操作系统后,情况就变得大不一样了,电脑可以同时运行多个程序。通过 TOP 命令可以查看电脑上当前正在运行的进程(和程序有着密切的关系),见下图。

通常情况下,一个程序会至少对应一个进程。上图中,“Google Chrome”这三个进程意味着我的电脑上打开着一个名叫谷歌浏览器的程序。

让我们用一段专业的术语来描述一下程序和进程之间的关系:

程序是计算机为完成特定任务所执行的指令序列。 操作系统允许多道程序并发执行共享系统资源,而程序在并发执行时所产生的一系列特点使得传统的程序概念已经不足以对其进行描述,因此,引入了“进程(Process)”:可以更好的描述计算机程序的执行过程,反映操作系统的并发执行、资源共享及用户随机访问的特性,并以此作为资源分配的基本单位。

每当一个程序运行时,操作系统就为该程序创建了一个进程,并为它分配资源、调度其运行。程序执行结束后,进程也就消亡了。一个程序被同时执行多次,系统就会创建多个进程。因此,一个程序可以被多个进程执行,一个进程也可以同时执行多个程序。

当然了,对于现在的操作系统来说,进程并不是最小的调度单位,而是线程。线程也被称为轻量级进程。

由于同一个进程中的所有线程会共享进程的内存地址空间,因此这些线程都能访问相同的变量,如果没有明确的同步机制来协同对共享数据的访问,那么当一个线程正在使用某个变量时,另外一个线程可能同时访问这个变量,就会造成不可预测的结果。

02、多线程的优势

查看了一下,我这台电脑的物理 CPU(处理器)个数只有一个,但是核数(一块 CPU 上面能处理数据的芯片组的数量)是 4 个。

这意味着,我这台电脑能够在同一时间处理一个进程内的四个线程任务:线程 A 正在读取一个文件,线程 B 正在写入一个文件,线程 C 正在计算一个数值,线程 D 正在进行网络传输。

我们知道,进行文件读写或者网络传输通常会发生阻塞,这也是没办法的事。如果没有多线程的帮助,程序会按照顺序依次执行,也就意味着发生阻塞的时候其他任务只能干巴巴的等着,什么也做不了。

有了多线程,情况就完全不一样了,线程之间可以互不干扰,从而发挥处理器的多核能力。

说个有点让人难为情的事,我是 Eclipse 的(愚)忠实用户,至今没切换到 IDEA 阵营。在用 Eclipse 的时候经常会出现这样的情况,一个进度被另外一个卡住,下一个必须等待上一个执行完毕才开始执行。等待的时候几乎什么也干不成,点了取消也没用!

假如 Eclipse 采用多线程的话,每个任务放在单独的任务中执行,响应就会快很多。

03、多线程带来的风险

曾有这样一则耳熟能详的故事。

特洛伊人在城外的海滩上发现了一只巨大的木马,他们把它拉进了城里而不是把它烧掉或推到海里,以为这是天神给特洛伊人带来的赐福。于是,特洛伊人欢天喜地,庆祝胜利,他们跳着唱着,喝光了一桶又一桶的酒,以为希腊人被他们战败了。

而故事的结局大家也都知道了。希腊人把特洛伊城掠夺成空,烧成一片灰烬。海伦(宙斯之女,被称为“世上最美的女人”,她和特洛伊王子私奔,引发了特洛伊战争)也被墨涅依斯带回了希腊。

海伦

多线程带来了无与伦比的好处,但也潜藏了巨大的风险(就像那个木马)。其中尤为突出的就是安全性问题。

代码语言:javascript
复制
public class Unsafe {
  private int chenmo;
  public int add() {
    return chenmo++;
  }
}

上面这段代码在单线程的环境中可以正确执行,但在多线程的环境中则不能。递增运算 chenmo++ 可以拆分为三个操作:读取 chenmo,将 chenmo 加 1,将计算结果赋值给 chenmo。两个线程可能交替执行,发生下图中的情况,于是两个线程就会返回相同的结果。这也是最常见的一种安全性问题。

其次,多线程还会引发活跃性问题:线程 B 需要等待线程 A 释放它们共有的资源,而线程 A 由于一些问题导致无法释放资源,那么线程 B 就只能苦苦地等下去。

再者,多线程还会引发性能问题(设计良好的多线程当然会提高性能):当线程调度器临时挂起一个活跃中的线程转而运行另外一个线程时,就会频繁地出现上下文切换(Context Switch)——开销很大(挣得多花的也多)。

04、单核 CPU 和多核 CPU

来思考一个问题吧。假如 CPU 只有一个,核数也只有一个,多线程还会有优势吗?

闭上眼,让思维旋转跳跃会。

来看答案吧。

单核 CPU 上运行的多线程程序,同一时间只有一个线程在跑,系统帮忙进行线程切换;系统给每个线程分配时间片(大概 10ms)来执行,看起来像是在同时跑,但实际上是每个线程跑一点点就换到其它线程继续跑。所以效率不会有所提高,线程的切换反到增加了系统开销。

那多核 CPU 呢?

当然有优势了!多核需要多线程才能发挥优势(不然巧妇难为无米之炊啊),同样,多线程要在多核上才能有所发挥(好马配好鞍啊)。

多核 CPU 多线程不仅善于处理 IO 密集型的任务(减少阻塞时间),还善于处理计算密集型的任务,比如加密解密、数据压缩解压缩(视频、音频、普通数据等),让每个核心都物尽其用。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-08-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 沉默王二 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 01、为什么需要操作系统
  • 02、多线程的优势
  • 03、多线程带来的风险
  • 04、单核 CPU 和多核 CPU
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档