《深入理解JVM》第十二章 高效并发(JAVA与线程)

版权声明:版权为ZZQ所有 https://blog.csdn.net/qq_39148187/article/details/81672026

并发并不一定依赖多线程,(如php中常见的多进程并发) 但是java 中的并发和线程不开关系

Thread类的大部分方法都是native方法, native方法意味着,这个方法没有使用和平台无关的手段实现,或者是无法使用,当然也可能是为了执行效率 

实现线程主要有三种方式

1. 内核线程实现, 

2 ,使用用户线程实现

3.用户线程加轻量级进程混合实现

使用内核线程实现

内核线程就是直接由操作系统内核支持的线程,这种线程由内核来实现在每个线程上切换,内核通过操作操纵调度器多线程进行调度,并负责把线程的任务映射到各个处理器,每个内核线程可以视为内核的分身,支持多线程的内核叫做多线程内核

   程序一般不会使用内核线程,而失去使用内核线程的一个高级接口,---轻量级进程,由于每个轻量级进程都有一个内核线程支持,因此只有先支持内核线程才能有轻量级进程,

由于内核线程的支持,每个线程都成了一个独立的调度单元,即使有一个轻量级的进程在系统中阻塞,也不会影响整个进程的工作,但是轻量级进程有局限性,

它是由内核线程实现的,因此各种线程的操作, 创建 同步, 都需要系统的调用,系统调用耗费的代价是比较高的

 每一个轻量级进程都要一个内核线程的支持,因此轻量级进程要耗费一定的内核资源, 因此一个系统支持轻量级进程是有限的

用户使用用户线程实现

从广义上讲,一个线程不是内核线程就是用户线程,轻量级进程也属于用户线程,轻量级进程使用是在内核上,许多操作都要进城系统调用,效率会受到限制

  而狭义上的用户线程指的是完全建立在用户空间的线程库上,系统内核不能感知线程存在的实现,用户线程的建立 同步 销毁 完全是在用户态中完成,不需要内核帮忙,如果程序实现的当, 这种线程不需要内核帮忙,因此这种效率是很低的可以支持规模更大的线程数量,这种进程与用户线程的关系是1:N的关系

这种实现的优势在于不需要内核线程的支援

不足在于没有系统内核的支援,由于操作系统把处理器资源分配到进程,哪诸如 线程阻塞如何处理,多处理器系统中如何将线程映射到其他处理器上,这类问题解决非常困难, java ruby 都是用过用户线程,但是都放弃了

使用用户线程加轻量级的进程混合使用

即存在用户线程,也存在轻量级进程,用户线程完全建立在用户的空间中,用户线程的创建销毁切换都是非常的廉价的,并且可以支持大规模的并发,而操作系统提供轻量级进程作为用户线程和内核线程的桥梁,这样可以使用内核提供的线程调度功能以及处理器映射,并且用户线程系统调用可以通过轻量级线程完成,这样降低了阻塞的风险,用户线程和轻量级线程未N:M 的关系

UNIX 操作系统,Solaris  HP-UX 都提供N:M线程模型实现

Java线程实现

Sun JDK 他的windows 版本可Linux 版本都是一对一线程模型实现的,一条java线程就映射到一个轻量级线程中,因为windows 和linux 系统提供了线程模型是 1:1 

但是在Solaris 平台中,由于操作系统的线程特性可以同时1:1 也可以多对多,因此Solaris 的jdk版本提供两个平台专有的虚拟机参数

-XX:+UseLWPSynchronization (默认值) -XX:+:USeBoundThreads 来明确规定虚拟机使用那种线程莫能行

java 线程调度

线程调度指系统为线程分配处理器使用权的过程,主要调度模式有两种, 

1. 同式线调度

2。抢占式线程调度

如果式协同式调度多线程系统,线程的执行时间是有线程本身控制的, 线程把自己的工作执行完之后,要主动通知系统切换到另一个线程上去,协同式多线程的最大好处是实现简单, 弊端是 线程的执行时间不可控制,如果代码写的有问题一直阻塞,也不知道怎么了

如果使用抢占式多线程系统,那么每个线程将有系统来分配时间,线程的切换有系统来决定,java中的thread.yield() 可以让出执行时间,但是要获取执行时间的话线程没有办法,这样来说,一个线程阻塞也没问题, 从广义来讲,java使用抢占式线程调度,

虽然java 的线程调度是系统完成的,但是介意给一些线程分配点执行时间,java 设置了10 个现车优先级, 在两个线程都是ready的状态, 谁的优先级高谁先ready

不过优先级线程并不是多靠谱,因为java 的线程是通过映射到系统的原生线程实现的,所以线程的调度还是取决于操作系统,

windows 有一个优先级推动器  proiority boosting  哪个线程勤奋推他一把,让他更努力,所以有可能不会按照线程优先级

状态转换

java 语言定义了5线程状态,一个线程同一时间, 有且只能有一个状态

new 新建 : 创建线程但是没有启动

runable运行: funable包括了操作系统线程状态中的Running 和Ready 也就是处于此状态的先成功有可能正在执行,又有可能正在等待cpu为他分配执行时间

Waiting 无限期等待: 处于这种状态,线程永远不会被cpu分配执行时间,他们要等到其他的线程显式的唤醒,以下方法会让线程编程waiting状态

     没有设置参数的 Object.wait() 

    没有设置Timeout参数的Thread.join()方法

    LockSupport.park()方法

Time Waiting 有限日期等待   处于这种状态的线程不会被分配cpu执行时间 ,不过无须等待被其他线程显式的唤醒,在一定时间之后提供会自动唤醒他,

Thread.sleep()方法

。。。

阻塞(Blocked) :线程被阻塞,阻塞状态和等待状态区别是,阻塞状态在等待获取排他锁,整个事件将另外一个线程放弃锁的时候发生:而等待状态是等待一段时间或者唤醒动作的发生,

猜你喜欢

转载自blog.csdn.net/qq_39148187/article/details/81672026