哈喽,大家好,我是世杰。

本次给大家介绍一下操作系统线程和Java的线程以及二者的关联

1. 面试连环call

  1. Java线程可以无限创建吗?
  2. Java线程和操作系统线程有什么关联?
  3. 操作系统为什么要区分内核态和用户态?

要想解答这些问题,我们要先从操作系统线程开始说起,让我们开始吧


2. 操作系统线程

2.1 内核态和用户态

根据进程访问资源的特点,我们可以把进程在系统上的运行分为两个级别:

  • 用户态(User Mode) : 用户态运行的进程可以直接读取用户程序的数据,拥有较低的权限

  • 内核态(Kernel Mode):内核态运行的进程几乎可以访问计算机的任何资源包括系统的内存空间、设备、驱动程序等,不受限制,拥有非常高的权限。当操作系统接收到进程的系统调用请求时,就会从用户态切换到内核态,执行相应的系统调用,并将结果返回给进程,最后再从内核态切换回用户态。

那为什么要区分用户态和内核态呢?

  • 在 CPU 的所有指令中,有一些指令是比较危险的比如内存分配设置时钟IO 处理等,如果所有的程序都能使用这些指令的话,会对系统的正常运行造成灾难性地影响。因此,我们需要限制这些危险指令只能内核态运行。这些只能由操作系统内核态执行的指令也被叫做 特权指令

  • 如果计算机系统中只有一个内核态,那么所有程序或进程都必须共享系统资源,例如内存、CPU、硬盘等,这将导致系统资源的竞争和冲突,从而影响系统性能和效率。并且,这样也会让系统的安全性降低,毕竟所有程序或进程都具有相同的特权级别和访问权限。

2.2 用户态线程

早期的操作系统中,所有的线程都是在用户态下实现,操作系统只能调度线程所属的进程,而无法调度线程

在这种模型下,用户需要自己定义线程的数据结构、创建、销毁、调度和维护等,这些线程运行在某个进程内,操作系统直接对进程进行调度

『优点』

  • 即使操作系统原生不支持线程,我们也可以通过库函数来支持线程
  • 线程的调度只发生在用户态,避免了操作系统从内核态到用户态的转换开销。

『缺点』

  • 由于操作系统无法调度线程,CPU 的时间片切换是以进程为维度的,如果进程中某个线程进行了耗时比较长的操作,那么由于用户态中没有时钟中断机制,就会导致此进程中的其它线程因为得不到 CPU 资源而长时间的持续等待;
  • 如果某个线程进行系统调用时比如缺页中断而导致了线程阻塞,此时操作系统也会阻塞整个进程,即使这个进程中其它线程还在工作。

2.3 内核态线程

现代操作系统,包括 Windows、Linux、Mac OS X 和 Solaris 等,都支持内核线程。线程运行在内核空间,直接由内核负责,由内核来完成调度。

此时我们可以直接使用操作系统中已经内置好的线程,线程的创建、销毁、调度和维护等,都直接由操作系统的内核来实现,我们只需要使用系统调用就好了,不需要像用户级线程那样自己设计线程调度。

内核线程和用户线程的对应关系并不完全是1对1,其关联模式有三种

2.4 线程模型

多对一线程模型

多个用户线程对应到同一个内核线程上,线程的创建、调度、同步的所有细节全部由进程的用户空间线程库来处理。这样,极大地减少了创建内核态线程的成本,但是线程不可以并行。因此,这种模型现在基本上用的很少。

『优点』

  • 用户线程的很多操作对内核来说都是透明的,不需要用户态和内核态的频繁切换。使线程的创建、调度、同步等非常快。

『缺点』

  • 由于多个用户线程对应到同一个内核线程,如果其中一个用户线程阻塞,那么该其他用户线程也无法执行
  • 内核并不知道用户态有哪些线程,无法像内核线程一样实现较完整的优先级调度等操作

一对一线程模型

该模型为每个用户态的线程分配一个单独的内核态线程,在这种情况下,每个用户态都需要通过系统调用创建一个绑定的内核线程。 这种模型允许所有线程并行执行,能够充分利用多核优势。目前 Linux 中的线程OpenJDK Java 线程等采用的都是一对一线程模型。每一个JVM线程,都有一个对应的内核线程。

『优点』

  • 解决了多对一模型的阻塞调度问题
  • 实现起来较为简单

『缺点』

  • 每创建一个用户线程,相应地就需要创建一个内核线程,开销较大,因此需要限制整个系统的线程数量
  • 对用户线程的大部分操作都会映射到内核线程上,引起用户态和内核态的频繁切换

多对多线程模型

这种模式下会为 n 个用户态线程分配 m 个内核态线程。m 通常小于 n。一种可行的策略是将 m 设置为核数。这种多对多的关系,减少了内核线程,同时也保证了多核心并行。多对多模型中线程的调度需要由内核态和用户态一起来实现,例如线程间同步需要用户态和内核态共同实现。用户态和内核态的分工合作导致实现该模型非常复杂。

PS: Linux多线程模型曾经也想使用该模型,但它太复杂,要对内核进行大范围改动,所以还是采用了一对一的模型

『优点』

  • 多对多模型将任意数量的用户线程复用到相同或更少数量的内核线程上,结合了一对一和多对一模型的最佳特性
  • 用户对创建的线程数没有限制

『缺点』

  • 实现起来非常复杂

3. Java 线程

3.1 线程库

在进入 Java 线程主题之前,有必要讲解一下线程库 Thread library 的概念。

线程库就是为开发人员提供创建和管理线程的一套 API。线程库不仅可以在用户空间中实现,还可以在内核空间中实现。前者涉及仅在用户空间内实现的 API 函数,没有内核支持。后者涉及系统调用,也就是说调用库中的一个 API 函数将会导致对内核的系统调用,并且需要具有线程库支持的内核。

下面简单介绍下三个主要的线程库:

  • POSIX线程:是[POSIX]的[线程]标准,定义了创建和操纵线程的一套[API]。实现POSIX线程标准的库常被称作pthreads,一般用于[Unix-like] POSIX系统,如[Linux]、 [Solaris]。

  • Win32 线程:用于 Window 操作系统的内核级线程库

  • Java 线程:Java 线程 API 通常采用宿主系统的线程库来实现,也就是说在 Win 系统上,Java 线程 API 通常采用 Win API 来实现,在 UNIX 类系统上,采用 Pthread 来实现。

3.1 Java线程模型

  • 在 JDK 1.2 之前,Java 线程是基于称为 "绿色线程"(Green Threads)的用户级线程实现的,JVM 开发了自己的一套线程库或者说线程管理机制。

  • 在 JDK 1.2 及以后,JVM 选择了更加稳定且方便使用的操作系统原生的内核级线程,通过系统调用,将线程的调度交给了操作系统内核。而对于不同的操作系统来说,它们本身的设计思路基本上是完全不一样的,因此它们各自对于线程的设计也存在种种差异,所以 JVM 中明确声明了:虚拟机中的线程状态,不反应任何操作系统中的线程状态

因此,现今 Java 中线程的本质,其实就是操作系统中的线程,其线程库和线程模型很大程度上依赖于操作系统(宿主系统)的具体实现,比如在 Windows 中 Java 就是基于 Wind32 线程库来管理线程,且 Windows 采用的是一对一的线程模型

3.2 Java线程创建数量

每个线程都有一个线程栈空间通过-Xss设置,可以通过JVM配置,JVM的默认栈大小

不考虑系统限制,可以通过如下公式计算,得出最大线程数量

线程数量=(机器本身可用内存-JVM分配的堆内存)/Xss的值

根据计算公式,得出如下结论:

  • 结论1:JVM堆越大,系统创建的线程数量越小。

  • 结论2:当-Xss的值越小,可生成线程数量越多。

假如我们的容器内存大小是8G,堆大小是4096M,走-Xss默认值,可以得出 最大线程数量:4096个。

我们知道操作系统分配给每个进程的内存大小是有限制的,比如32位的Windows是2G。因此操作系统对一个进程下的线程数量是有限制的,不能无限的增多。

如果考虑系统限制,主要跟以下几个参数有关系

  • /proc/sys/kernel/pid_max 增大,线程数量增大,pid_max有最高值,超过之后不再改变,而且32,64位也不一样

  • /proc/sys/kernel/thread-max 系统可以生成最大线程数量

线程是非常宝贵的资源,我们要严格控制线程的数量


『引用』:

Threads

Java 线程和操作系统的线程有啥区别?

一台 Java 服务器可以跑多少个线程?

操作系统常见面试题总结(上)

用户态线程和内核态线程的区别

面试官:Java线程可以无限创建吗?的更多相关文章

  1. 面试官问线程安全的List,看完再也不怕了!

    最近在Java技术栈知识星球里面有球友问到了线程安全的 List: 扫码查看答案或加入知识星球 栈长在之前的文章<出场率比较高的一道多线程安全面试题>里面讲过 ArrayList 的不安全 ...

  2. 面试官:线程池如何按照core、max、queue的执行循序去执行?(内附详细解析)

    前言 这是一个真实的面试题. 前几天一个朋友在群里分享了他刚刚面试候选者时问的问题:"线程池如何按照core.max.queue的执行循序去执行?". 我们都知道线程池中代码执行顺 ...

  3. Java线程池的创建详解

    本篇文章主要总结了Java创建线程池的三种方式以及线程池参数的详细说明,对线程池感兴趣的同学可以作为参考学习. 1)通过工具类java.util.concurrent.Executors的静态方法来创 ...

  4. JAVA线程池的创建与使用

    为什么要用线程池? 我们都知道,每一次创建一个线程,JVM后面的工作包括:为线程建立虚拟机栈.本地方法栈.程序计数器的内存空间(下图可看出),所以线程过多容易导致内存空间溢出.同时,当频繁的创建和销毁 ...

  5. java线程池及创建多少线程合适

    java线程池 1.以下是ThreadPoolExecutor参数完备构造方法: public ThreadPoolExecutor(int corePoolSize,int maximumPoolS ...

  6. java线程基础巩固---创建并启动线程

    对于java的并发编程方面的东东,不管是面试还是实际工作开发都是非常重要的,而往往只要涉及到并发相关的东东有点让人觉得有点难,而实际工作中涉及到并发可能就是简单的用下同步块.上锁之类的一些简单的操作, ...

  7. java线程池的创建使用

    利用java的多线程编程可以大大的提高系统的并发运行效率,线程越多并发执行的任务就越多,但是并不意味着效率会一直提高,相反会得到适得其反的效果. java中的多线程编程一共有三种方法: 继承Threa ...

  8. java线程一之创建线程、线程池以及多线程运行时间统计

    线程和进程的基本概念 进程和线程是动态的概念.         进程是 "执行中的程序",是一个动词,而程序是一个名词,进程运行中程序的"代码",而且还有自己的 ...

  9. java线程——三种创建线程的方式

    前言 线程,英文Thread.在java中,创建线程的方式有三种: 1.Thread 2.Runnable 3.Callable 在详细介绍下这几种方式之前,我们先来看下Thread类和Runnabl ...

  10. 死磕 java线程系列之创建线程的8种方式

    (手机横屏看源码更方便) 问题 (1)创建线程有哪几种方式? (2)它们分别有什么运用场景? 简介 创建线程,是多线程编程中最基本的操作,彤哥总结了一下,大概有8种创建线程的方式,你知道吗? 继承Th ...

随机推荐

  1. Golang使用正则

    目录 正则在线测试网站 Golang标准库--regexp 相关文章 课程学习地址: 手册地址: dome 正则在线测试网站 https://regex101.com/ Golang标准库--rege ...

  2. U.2与M.2接口

    U.2接口 U.2接口别称SFF-8639,是由固态硬盘形态工作组(SSD Factor Work Group)推出的接口规范.U.2接口不但能支持SATA-Express(一种PCI-E与SATA混 ...

  3. WEB服务与NGINX(14)-NGINX的压缩功能

    1. nginx压缩功能 nginx支持对指定类型的文件进行压缩后再回传给客户端,而且压缩可以设置压缩比,压缩后的文件会明显变小,有助于降低出口带宽的利用率,但是会占用一定的CPU资源. nginx实 ...

  4. postgresql数据库清理

    大量update或者delete后 磁盘空间会猛增.原理是postgresql并没有真正的删除 只是将删除数据的状态置为已删除,该空间不能记录被从新使用.若是删除的记录位于表的末端,其所占用的空间将会 ...

  5. C语言:输入一个整数并让其逆反输出。123->321

    主要思想为: a)计算输入的位数有多少个 b)计算出最高位的单位(若最高位为是万位, 那么需要一个变量存储最高位数值1000) c)用取模的方法从个位数开始进行取出每一个单位上的数字 d)从个位数开始 ...

  6. JDK源码阅读-------自学笔记(二十二)(java.util.ArrayList自定义晋级,ArrayList实战详解)

    简介(Introduction)   上篇文章主要介绍了ArrayList自行模仿建立的方式,那么,其实这个类不是一次性就那么完美的,现在做一个一步步变成那样完整的ArrayList的版本升级测试. ...

  7. 在线电子表格编辑器 Luckysheet

    下载地址 不知道地址正不正经,我先用着,网上找的地址,不知道是不是可信任的,疑似官网的两个地址都打不开, https://github.com/dream-num/Luckysheet zip包  h ...

  8. 5款.NET开源、免费、功能强大的图表库

    LiveCharts2 LiveCharts2是一个.NET开源(MIT License).简单.灵活.交互式且功能强大的.NET图表.地图和仪表,现在几乎可以在任何地方运行如:Maui.Uno Pl ...

  9. MindSponge分子动力学模拟——体系控制(2024.05)

    技术背景 在传统的分子动力学模拟软件中,对于分子体系的控制,例如控制体系的相对位置亦或是绝对位置,通常都是通过施加一些约束算法来实现的.例如用于限制化学键的LINCS算法,又比如水分子体系非常常用的S ...

  10. C# 借助NPOI 完成 xls 转换为xlsx

    背景:MinExcel开源类库,导数据的库,占用内存很低,通过io,不通过内存保存,不支持 xls格式的文件,支持csv和xlsx,所以要想使用这个库,就得把xls格式转换为xlsx.只复制了数据 合 ...