zl程序教程

您现在的位置是:首页 >  后端

当前栏目

【Java 并发编程】线程简介 ( 进程与线程 | 并发概念 | 线程间通信 | Java 并发 3 特性 )

2023-06-13 09:17:56 时间

文章目录

一、进程与线程


最开始是没有线程这个概念的 , 一个应用程序就是一个进程 , 应用程序运行时 , 如果还要处理与用户交互的逻辑 , 二者只能 交替进行 , 这样 CPU 执行效率就很低 ;

CPU 是整个计算机系统中的 稀缺资源 , 程序的运行 , 计算 都需要依赖 CPU 完成 ;

为了 高效利用 CPU 这个稀缺资源 , 引入了线程概念 ;

进程 : 每个应用都是一个独立进程 , 是 资源分配 , 调度 的最小单元 ;

线程 : CPU 调度的最小单元 ;

二、并发


CPU 是多核的 ;

进程 是在 物理内存 中执行的 ( 内存条 或 RAM ) ;

每个进程 中 有若干 线程 ;

CPU 运行线程时 , 通过 OS 线程调度 , 在 某个 CPU 的 某个 核 上 执行 某个 进程 的 某个 线程 ;

程序的执行 , 最终是靠指令进行执行 ;

进程 在 内存中 , 会被划分一块 独立的区域 , 每个进程之间的内存都是 隔离 的 , 一个进程的崩溃 , 不会影响其它进程 ;

每个线程执行时 , JVM 都会为该线程单独分配 线程栈 , 本地方法栈 , 程序计数器 , 三者都是线程独有的数据 ;

程序运行 的 指令 , 就放在 上面的 线程栈 中 ;

每个 线程栈 中都有 一串指令 , 等待执行 ;

这些线程栈 , 不能 串行 执行 , 必须 并发 执行 , 才能保证所有的应用程序 , 都能得到很好的用户体验 ;

并行 是 同一个 时间点 处理多个事件 ; 并发 是 同一个 时间段 处理多个事件 ;

三、线程间通信


线程间通信 :

假设有

2

个线程 A 和 B ;

线程一旦执行后 , 会在内存中分配 线程栈 , 该线程栈中有一块 本地内存 ;

有一些对象是共享的 , 所有线程都可以访问 , 如 堆内存 , 在 线程栈 中的 本地内存 中 , 有一个 共享变量的副本 ;

在 主内存 中 , 有很多 共享变量 ;

主内存中有变量 int a = 1 , 如果线程 A 中想要访问变量 a , 就会将该变量 int a = 1 变量 复制到 线程 A 的 本地内存中 ;

如果线程 B 也想访问 , 则将该变量 int a = 1 变量 复制到 线程 B 的 本地内存中 ;

如果在 线程 A 中 , 对变量 a 进行 +1 操作 , 只是对 线程 A 本地内存 中的 变量 a 副本进行了 +1 操作 , 主内存 和 线程 B 中的 a 变量 没有变化 ;

假如 线程 A 和 线程 B 同时对 本地内存 中的变量 a 进行操作 , 那么就有可能出现 a 取值异常的情况 ;

主内存 中的数据 , 对所有的线程都可见 ; 但是 线程 A 和 线程 B 之间 , 互相不知道对方线程 本地内存 中的数据 ;

这种情况就是线程不安全的情况 ;

四、Java 并发 3 特性


Java 并发的

3

特性 :

  • 原子性 : 每个操作都是 不可拆分的原子操作 ; 在线程中进行 a++ 就不是原子操作 , 该操作分为
3

个步骤 , 首先从主内存中读取 a 变量 , 然后进行自增操作 , 最后在将自增后的值写回主内存中 ;

  • 可见性 : 多个线程 访问同一个变量 , 该变量一旦被 某个线程修改 , 这些线程必须可以 立刻看到被修改的值 ;
  • 有序性 : 程序按照 代码先后顺序 执行 ;