[短文速读 -5] 多线程编程引子:进程、线程、线程安全

前言

最近在总结《Java多线程编程核心技术》这本书。实话实说:多线程编程核心技术,这些字眼属实有些夸大。面试

可是也不能由于此,就直接否定了书籍自己的价值。这是一篇比较适合入门阅读的书籍。和我最近在尝试写的文章有类似之处,也就是尽力让知识点,少思考性而多阅读性。编程

所以接下来会将这本书的内容,揉到个人接下来的文章中,旨在:真正能在碎片化时代下,进行有效学习。安全

爱因斯坦:“若是你不能简单地解释同样东西,说明你没真正理解它。”多线程

[短文速读-1] a=a+b和a+=b的区别并发

[短文速读-2] 重载/重写,动/静态分派?(从新修订)工具

[短文速读-3] 内部匿名类使用外部变量为何要加finalpost

[短文速度-4] new子类是否会实例化父类性能

[短文速读 -5] 多线程编程引子:进程、线程、线程安全学习

正文

毫无疑问,一切的开始。确定是先介绍介绍概念性的东西。主题是线程,可是谈到线程,势必不能忘了进程。所以让咱们先来聊一聊线程和进程的概念。操作系统

接下来让咱们有请文章一向的主角:小AMDove出场~

进程和线程

小A:MDove,我最近在思考一个问题,多线程多线程。那到底什么是多线程呢?

MDove:想要理解多线程,其实就要不得不提一提:进程,以及进程和线程之间的关系。

一个比较通俗且常见的解释:进程:操做系统分配资源的基本单位;线程:操做系统调度最小单位。

稍稍学院派的解释:

来自《如今操做系统(第4版)》 + 维基百科 + 百度百科

进程:

  • 进程的本质是正在执行的一个程序,进程基本上上容纳运行一个程序所须要的全部信息的容器。
  • 在当代多数操做系统中,进程自己不是基本运行单位,而是线程的容器。程序自己只是指令、数据及其组织形式的描述,进程才是程序的真正运行实例。
  • 早期面向进程设计的计算机结构中,进程是系统进行资源分配和调度的基本单位。

小A:哦?既然进程是程序的实体,那么只要进程不就好了?

MDove:这固然是没有问题啦。可是,一个致命的问题,你们都追求快,更快,很是快!

小A:不不不不不,我就追求慢,坚挺~

MDove:坚挺是吧,你这么秀,你怎么不去Tokyo Hot?搁这给我扯犊子。学不学了?不学你去找加藤鹰去。

小A:学学学,个人理解:是否是线程比进程占用资源更少?

MDove:其实关于消耗资源这个问题很难回答。好比Linux、Windows对进程和线程的设计就是不一样的。若是从Linux的角度出发,进程和线程不管是建立仍是上下文切换其实不在极端状况下,所谓的性能仍是资源,差距并非很大。差距比较大的一点是:进程是内存独立,而线程内存共享。

MDove:固然,两者均可以悄摸得去作一些事情,但不一样点在于:进程间通信,远比线程间通信复杂的。所以在上层高级语言的设计上,线程便成了不错的用于后台完成耗时操做的一个工具。可是不能否认的一点,多进程一样扮演者举足轻重的角色!打个比方,单进程的程序,若是杀死这个进程那么这个进程所依附的全部线程所有死亡。而多进程则不怕,毕竟彼此是独立运行的进程,所以多进程在拉活方面有着不俗的战斗力。

小A:哦~原来如此,那能够聊一聊线程么?

MDove:好的,接下来让咱们看一看线程。


线程:

  • 是操做系统可以进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运做单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中能够并发多个线程,每条线程并行执行不一样的任务。
  • 线程能够为操做系统内核调度的内核线程;由用户进程自行调度的用户线程

MDove:举个小例子:打开咱们计算机上的任务管理器时,进程Tab页上,咱们看到的就是进程;而独立进程程序的子任务就是线程(不绝对,也能够存在多进程的程序)。好比:QQ运行时(进程),就有不少子任务(线程)在同时运行:你即能一遍和基友视频,一遍还能和其余基友文字聊天这就体现了多线程,其中每一项子任务均可以理解为线程

MDove:对于咱们开发者来讲线程是一个很常见的概念。对于Java后台来讲,可以熟练的掌握对多线程的使用。能够说是掌握核心科技同样。

小A:???听你这么说,多线程没什么难的呀?

多线程的弊端

MDove:初生牛犊不怕虎,但你要明白,虎终究是虎。多线程的一大难点在于线程安全问题。由于内存共享的缘由,致使了线程刷新内存的滞后性。

小A:???什么意思???

MDove:打个比方,在Java线程模型中:每一个线程运行时,都会把主内存中的变量值复制到本身的工做内存当中,当本身执行完毕后,在把计算完毕的工做内存中的变量,反过来赋值给主内存。

小A:嗯?这好像没什么问题啊?

MDove:没问题?问题大了去了!我们举一个花钱的例子:如今我们帐本上有十个亿。你是一个线程,我是一个线程。

  • 我先执行了,我拿了一个亿,去建设了一下社会主义核心价值观,而后我在个人帐本里记了一下帐:我拿了1个亿,手头还有9个亿

此时我们的帐本还剩9个亿

  • 接下来,你也出动了,你拿了9个亿中的一个亿,你也在你的帐本里记了一下帐:我拿了1个亿,还有8个亿。而后你去吸烟喝酒烫头了。

此时我们的帐本还剩8个亿

  • 这个时候我干完了个人事,我花了5千万,还剩5千万。而后对于我来讲个人帐本变成了,还有9亿5千万。此时我把个人帐本写到了我们们公共帐本里...

小A:等会等会?你想啥呢?钱越花越多了!我都拿走1个亿了,你那咋还9个亿呢?你就不会同步一个个人帐本么?

MDove:没错呀,我就不会同步一个你的帐本呀!这就是多线程的问题因此。由于每一个线程是独立运行的,谁都无论谁,所以,如何同步线程之间的数据便成了相当重要的一点!

小A:这么一说我就明白了,那怎么同步呢?

保证线程安全

可见性,原子性

MDove:其实刚才的问题就出如今帐本的不一样步上,所以若是咱们可以解决帐本的同步问题,理论上就能够解决我们的线程安全问题。固然你能够用一些手段通知我,让我更新个人帐本(可见性)。可是仍存在问题,若是咱们写帐本的操做是个多步骤的复杂操做,可能就会存在问题了,由于这个里每一步通存在同步问题,只有当咱们的写帐本操做是一个单一操做(原子性)那么这种作法就是没有问题的。

小A:局限还挺多,那有没有其余方式呢?

加锁

MDove:接下来讲一个加锁的方式。举个我们上厕所的例子。咱们不少人都要上厕所,若是咱们的厕所没有任何措施,那么画面简直没法想象。所以,我们...那啥...大号...的时候,都会把门锁上。其余人一看门锁上了,也就只好默默的憋一会。

MDove:当咱们解决后,打开门,其余人就能够尽情释放了。

那么这个过程就至关于:一个线程在操做一个变量时,直接把这个变量锁起来。其余线程只能等着,所以确定就不会存在多个线程同时操做变量的问题了。

线程优先级

小A:那么接下来就是队伍中第一我的去...那啥么?

MDove:固然不是,线程的世界可没有什么先来后到。而是按线程的优先级去排列。那么若是没有优先级,那就看谁的拳头更硬谁的运气更好了。

小A:好残暴,那有没有顺利排列的可能性呢?那咱们可不能够本身固定一个顺序去开启线程的执行呢?

线程执行顺序

MDove:咱们固然能够指定一种策略去顺序的start咱们的线程,可是咱们只能保证线程start的顺序,没办法保证线程调度的顺序。由于对于线程来讲,何时可以得到操做系统的宠幸那是不肯定的。所以线程会有多种状态:

  • 新建(NEW),表示线程被建立出来还没真正启动的状态。

  • 就绪(RUNNABLE),表示该线程已经在 JVM 中执行,固然因为执行须要计算资源,它多是正在运行,也可能还在等待系统分配给它 CPU 片断,在就绪队列里面排队。

  • 阻塞(BLOCKED),阻塞表示线程在等待锁释放。好比,线程试图去获取某个锁,可是其余线程已经独占了,那么当前线程就会处于阻塞状态。

  • 等待(WAITING),表示正在等待其余线程采起某些操做。。

  • 终止(TERMINATED),不论是意外退出仍是正常执行结束,线程已经完成使命,终止运行。

固然也能够加上一个:运行(RUNNING):可运行状态(RUNNABLE)的线程得到了CPU时间片,开始执行代码。

分段锁

MDove:我们再回到那个厕所的例子。咱们平常中...厕所确定不止一个坑位,通常会有好几个。毕竟都是解决一样的问题,没有只设置一个坑位的道理。

MDove:因此对于咱们程序来讲也是如此,在面对类型的场景也会有相似的实现,这个方式就叫作分段锁。好比:ConcurrentHashMap,JDK1.8版本以前的设计。

MDove:固然关于锁这个话题,其实水是很深的。咱们嘚吧嘚说了这么多,其实就是在解决多线程安全问题。所以明白了吧,多线程是一个值得深刻学习的内容。

小A:学的我热血沸腾的,接下来教教我,Java中对线程的使用吧!

MDove:别急,聊了这么久厕所的话题,容我上个厕所,我们下期再来聊一聊线程的使用。

剧终

我是一个应届生,最近和朋友们维护了一个公众号,内容是咱们在从应届生过渡到开发这一路所踩过的坑,以及咱们一步步学习的记录,若是感兴趣的朋友能够关注一下,一同加油~

我的公众号:IT面试填坑小分队
相关文章
相关标签/搜索