稀土 2018-02-23
记得年前被同事问道“java是如何实现多线程?在网上搜索,基本上通篇都是源代码?什么集成Thread类,什么实现Runnable接口啊,但是原理是什么呢?”
当时这个问题让我沉思了一下,可能很多java程序员只是处于一个会写java代码的阶段,但是对java底层或者虚拟机没有深入的了解过。现在我就用我的理解简单描述一下java是如何在底层实现多线程的,如有不对之处希望大家指出错误,共同进步。
要搞清楚java如何实现多线程,就要弄明白java的程序是如何运行的?
java虚拟机(jvm)在执行java程序的过程中会把所管理的内存划分为若干个不同的数据区域,如下图。
数据区域共分为:java虚拟机栈,本地方法栈,程序计数器,堆,方法区。
由于本次的重点是java如何实现多线程,所以主要说明一下程序计数器,其他区域下一次会详细说明。
程序计数器是一个线程隔离的数据区,说白了就是每一个线程都会单独开辟一块内存区域给程序计数器,并且线程之间这块内存区域是隔离的,是安全的。
这块内存区域会非常小,但是却非常关键,他的主要作用是存储一段字节码,这段字节码记录的是当前线程下一条需要执行的字节码地址。简单点说就是,记录着一个位置,这个位置就是当前线程下一次需要执行的代码位置。
然而对于一个单核cpu来说,只能同时执行一条指令,但是如何实现多线程的呢?
这时候程序计数器就会起到决定作用了。
java虚拟机的多线程是通过线程轮流切换分配处理执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)都只会执行一条程序中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要一个独立的程序计数器,各条线程之间计数器互不影响,独立存储。
简单点说,对于单核处理器,是通过快速切换线程执行指令来达到多线程的,真正处理器就能同时处理一条指令,只是这种切换速度很快,我们根本不会感知到。