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

 

 

 

这篇文章的标题原本叫做——Java 并发编程(一):简介,作者名叫小二。但我在接到投稿时觉得这标题不够新颖,不够吸引读者的眼球,就在发文的时候强行修改了标题(也不咋滴)。

 

小二是一名 Java 程序员,就职于沉默公司,工龄是两年零一个月零三天。和刚毕业那会相比,编程能力已经大有提升,但领导老王一直没敢把并发编程的开发安排给小二,这让小二心里耿耿于怀。

这事不怪老王,小二心里很清楚:编写正确的程序很难,编写正确的并发程序更是难上加难。自己功力还不到那个份上,万一搞砸了,难免让一向谨慎的老王面上无光。

小二想来想去,办法只有一个,主动去学!就找老王要了一本《Java并发编程实战》,据说这本书是并发编程中的经典之作。拿到书后,随手翻了翻,竟然发现里面藏着一封情书:小二激动坏了,想象着老王写情话的样子,不由得笑出来声。

(戛然而止)

小二的背景就先介绍到这。接下来,我们来一起鉴赏下小二读完这本书后写下的第一篇文章。

Java 并发编程(一):简介

01、为什么需要操作系统

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

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

 

 

 

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

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

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

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

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

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

02、多线程的优势

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

 

 

 

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

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

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

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

 

 

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

03、多线程带来的风险

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

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

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

 

 

海伦

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

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 密集型的任务(减少阻塞时间),还善于处理计算密集型的任务,比如加密解密、数据压缩解压缩(视频、音频、普通数据等),让每个核心都物尽其用。

05、最后

亲爱的读者朋友们,小二投稿的第一篇文章到此就结束了。你对此感到满意吗?或者说你期待下一篇吗?

(此时的小二正在翘首以盼)

 

版权声明:本文为weixin_30522183原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_30522183/article/details/101416237

智能推荐

说说 Python Django 应用的基础目录结构

通过以下 django-admin 指令创建应用之后,就会生成应用的基础目录结构。 比如,我们建立了一个叫 ‘first’ 的应用,它的目录结构是这样的: 目录或文件 说明 最外层的 first/ 这是新应用的根目录,所有与该应用相关的内容都放在这里。 manage.py 用于管理 Django 项目的命令行工具。 里面一层的 first/ 目录 是一个...

Springboot整合rabbitMQ

依赖: 配置文件application.yml RabbitConfig 消息生产者RabbitProducer 消息消费者RabbitCustomer 通过Controller进行调用 启动项目后调用接口: 结果:...

Thread.join()方法的使用

如果一个线程A执行了thread.join()语句,代表当前线程A等待thread线程终止后才从thread.join()方法返回 并且这个方法具有超时特性,可以添加参数设置 输出结果: jdk中Thread.join()方法的源码(进行了部门调整)   每个线程终止的条件是前驱线程的终止,每个线程等待前驱线程终止后,才从join()方法返回,  当线程终止时,会调用自身的no...

linux服务器部署jenkins笔记

安装jenkins参考文档:https://blog.csdn.net/tomatocc/article/details/83930714 1. 打开jenkins官网:https://jenkins.io/download/ 将war包下载到本地 **ps:**这里要注意的是要下载左边下方的war包,不要下载右边下面的war包。左边是稳定版本,右边是最新版本,建议大家使用稳定版本(我刚开始下载的...

k8s部署elasticsearch集群

百度营销大学     环境准备 我们使用的k8s和ceph环境见: https://blog.51cto.com/leejia/2495558 https://blog.51cto.com/leejia/2499684 ECK简介 Elastic Cloud on Kubernetes,这是一款基于 Kubernetes Operator 模式的新型编排产品,用户可使用该产品在...

猜你喜欢

saas-export项目-AdminLTE介绍与入门

AdminLTE介绍 (1)AdminLTE是什么? AdminLTE是一款建立在bootstrap和jquery之上的开源的模板主题工具 (2)AdminLTE有什么特点? 提供一系列响应的、可重复使用的组件, 并内置了多个模板页面 自适应多种屏幕分辨率,兼容PC和移动端 快速的创建一个响应式的Html5网站 AdminLTE 不但美观, 而且可以免去写很大CSS与JS的工作量 AdminLTE...

MyBatis中ResultMap结果集映射

用于解决属性名和字段名不一致的情况: resultMap 元素是 MyBatis 中最重要最强大的元素。...

编写一个shell

编写shell的过程: 1.从标准输入中读入一个字符串。 2.解析字符串 3.创建一个子进程的执行程序。 4.子进程程序替换。 5.父进程等待子进程退出。...

WEB自动化测试中Xpath定位方法

前言: Xpath是在XML文档中查找信息的一种语言,使用路径表达式来选取XML文档中的节点或节点集,由于XML与HTML结构类似(前者用于传输数据,后者用于显示数据),所以Xpath也常用于查找HTML文档中的节点或节点集。 一  路径表达式: 路径以“/”开始     表示找到满足该绝对路径的元素; 路径以//”开始  ...

力扣困难难度 第4题 寻找两个正序数组的中位数

先看一眼题 我的思路: 设置下标i,j分别用于遍历两个数组,初始值均为0,直到找到两个数组中从小到大的第第length/2个数为止结束循环,length为两个数组长度之和。 ·每次比较nums[i]nums[j],如果前者小则i++,否则j++ ·循环结束时,如果count已经达到length/2,则说明已经找到了中位数,[注意:此时有可能正好其中一个数组遍历完了!所以...