JAVA并发编程基础

  • CPU核心

核心(Die)又称为内核,是CPU最重要的组成部分。CPU中心那块隆起的芯片就是核心,是由单晶硅以一定的生产工艺制造出来的,CPU所有的计算、接受/存储命令、处理数据都由核心执行。各种CPU核心都具有固定的逻辑结构,一级缓存、二级缓存、执行单元、指令级单元和总线接口等逻辑单元都会有科学的布局

CPU核心的发展方向是更低的电压、更低的功耗、更先进的制造、更先进的流水线架构和更多的指令集、更高的前端总线频率、集成更多的功能(例如集成内存控制器等等)以及双核心和多核心(也就是1个CPU内部有2个或更多个核心)等。CPU核心的进步对普通消费者而言,最有意义的就是能以更低的价格买到性能更强的CPU。

  • CPU核心数和线程数的关系和区别:
  1. CPU的核心数是指物理上,也就是硬件上存在有几个核心。举个例子,双核就是包括2个相对独立的CPU核心单元组,四核就包含4个相对独立的CPU核心单元组,等等,依次类推。
  2. 线程数是一种逻辑的概念,也就是模拟出的CPU核心数。例如,可以通过一个CPU核心数模拟出2线程的CPU,也就是说,这个单核心的CPU被模拟成了一个类似双核心CPU的功能。我们从任务管理器的性能标签页中看到的是两个CPU。 CPU的线程数概念仅仅只针对Intel的CPU才有用,因为它是通过Intel超线程技术来实现的,最早应用在Pentium4上。如果没有超线程技术,一个CPU核心对应一个线程。所以,对于AMD的CPU来说,只有核心数的概念,没有线程数的概念。CPU之所以要增加线程数,是源于多任务处理的需要。线程数越多,越有利于同时运行多个程序,因为线程数等同于在某个瞬间CPU能同时并行处理的任务数。

CPU之所以要增加线程数,是源于多任务处理的需要。线程数越多,越有利于同时运行多个程序,因为线程数等同于在某个瞬间CPU能同时并行处理的任务数。 

  • cpu线程数和Java多线程
  1. 线程是CPU级别的,单个线程同时只能在单个cpu线程中执行
  2. java多线程并不是由于cpu线程数为多个才称为多线程,当Java线程数大于cpu线程数,操作系统使用时间片机制,采用线程调度算法,频繁的进行线程切换。
  3. 线程是操作系统(CPU)最小的调度单位,进程是资源(比如:内存)分配的最小单位
  4. Java中的所有线程在JVM进程中,CPU调度的是进程中的线程

为什么要多线程? 一个进程里多线程之间可以共享变量,线程间通信开销也较小,可以更好的利用多核CPU的性能,多核CPU上跑多线程程序往往会比单线程更快,有的时候甚至在单核CPU上多线程程序也会有更好的性能,因为虽然多线程会有上下文切换和线程创建销毁开销,但是单线程程序会被IO阻塞无法充分利用CPU资源,加上线程的上下文开销较低以及线程池的大量应用,多线程在很多场景下都会有更高的效率

  • CPU时间片:CPU分配给每个线程的执行时间段,称作它的时间片。CPU时间片一般为几十毫秒(ms)。
  • 线程与进程

进程是操作系统的管理单位,而线程则是进程的管理单位;一个进程至少包含一个执行线程。不管是在单线程还是多线程中,每个线程都有一个程序计数器(记录要执行的下一条指令),一组寄存器(保存当前线程的工作变量),堆栈(记录执行历史,其中每一帧保存了一个已经调用但未返回的过程)。虽然线程寄生在进程中,但与他的进程是不同的概念,并且可以分别处理:进程是系统分配资源的基本单位,线程是调度CPU的基本单位

一个线程指的是进程中一个单一顺序的控制流,一个进程中可以并行多个线程,每条线程并行执行不同的任务。每个线程共享堆空间,拥有自己独立的栈空间

  1. 线程划分尺度小于进程,线程隶属于某个进程;
  2. 进程是CPU、内存等资源占用的基本单位,线程是不能独立占有这些资源的;
  3. 进程之间相互独立,通信比较困难,而线程之间共享一块内存区域,通信方便;
  4. 进程在执行过程中,包含:固定的入口、执行顺序和出口而进程的这些过程会被应用程序控制

进程与线程的关系:

    1、进程将CPU资源分给线程,即真正在CPU上运行的是线程。

    2、操作资源分配给进程,同一进程的所有线程共享该进程的所有资源。

  •  线程上下文切换

支持多任务处理是CPU设计史上最大的跨越之一。在计算机中,多任务处理是指同时运行两个或多个程序。从使用者的角度来看,这看起来并不复杂或者难以实现,但是它确实是计算机设计史上一次大的飞跃。在多任务处理系统中,CPU需要处理所有程序的操作,当用户来回切换它们时,需要记录和保存这些程序执行的数据。上下文切换就是这样一个过程,允许CPU记录并恢复各种正在运行程序的状态,使它能够完成切换操作。

多任务系统往往需要同时执行多道作业。作业数往往大于机器的CPU数,然而一颗CPU同时只能执行一项任务,如何让用户感觉这些任务正在同时进行呢? 操作系统的设计者 巧妙地利用了时间片轮转的方式, CPU给每个任务都服务一定的时间,然后把当前任务的状态保存下来,在加载下一任务的状态后,继续服务下一任务任务的状态保存及再加载, 这段过程就叫做上下文切换。时间片轮转的方式使多个任务在同一颗CPU上执行变成了可能。

上下文切换可以认为是内核(操作系统的核心)在 CPU 上对于进程(包括线程)进行以下的活动:

  1. 挂起一个进程,将这个进程在 CPU 中的状态(上下文)存储于内存中的某处;
  2. 恢复一个进程,在内存中检索下一个进程的上下文并将其在 CPU 的寄存器中恢复;
  3. 跳转到程序计数器所指向的位置(即跳转到进程被中断时的代码行),以恢复该进程。

上下文切换会导致额外的开销(示例程序:https://github.com/grayok/ecms/blob/master/ecms-web/src/test/java/com/test/concurrent/ContextSwitchTest.java),因此减少上下文切换次数便可以提高多线程程序的运行效率,减少上下文切换的方法有无锁并发编程、CAS算法、使用最少线程和使用协程

  1. 无锁并发:多线程竞争时,会引起上下文切换,所以多线程处理数据时,可以用一些办法来避免使用锁,如将数据的ID按照Hash取模分段,不同的线程处理不同段的数据;当任何特定的运算被阻塞的时候,所有CPU可以继续处理其他的运算。换种方式说,在无锁系统中,当给定线程被其他线程阻塞的时候,所有CPU可以不停的继续处理其他工作。无锁算法大大增加系统整体的吞吐量,因为它只偶尔会增加一定的交易延迟。大部分高端数据库系统是基于无锁算法而构造的,以满足不同级别
  2. CAS算法:Java提供了一套原子性操作的数据类型(java.util.concurrent.atomic包下),使用CAS算法来更新数据,不需要加锁。如:AtomicInteger、AtomicLong等;
  3. 最少线程:避免创建不需要的线程,比如任务很少,但是创建了很多线程来处理,这样会造成大量线程都处于等待状态;对于某个时间段任务量很大的这种情况,我们可以通过线程池来管理线程的数量,避免创建过多线程。
  4. 使用协程:即协作式程序,其思想是,一系列互相依赖的协程间依次使用CPU,每次只有一个协程工作,而其他协程处于休眠状态。如:JAVA中使用wait和notify来达到线程之间的协同工作。
  • 并行(concurrency)与并发(parallellism)

并发和并行两个概念很容易混淆。解释起来意思也差不多,不过说起来,并行才是真正意义上的并行执行,并发只是线程的交替执行,有可能存在串行的情况。

并行指两个或两个以上事件(或线程)在同一时刻发生,是真正意义上的不同事件或线程在同一时刻,在不同CPU资源上(多核),同时执行。并行,不存在像并发那样竞争CPU资源,等待执行的概念,因为并行状态下的线程分布在不同的CPU上,多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时。

并发的实质是一个物理CPU(也可以多个物理CPU) 在若干道程序(或线程)之间多路复用,并发性是对有限物理资源强制行使多用户共享以提高效率。通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。并发往往在场景中有公用的资源,那么针对这个公用的资源往往产生瓶颈,我们会用TPS或者QPS来反应这个系统的处理能力。

在单核CPU的系统,线程只能是并发的,而不能支持并行,并行执行只能存在与多核CPU的系统。

  1. 解释一:并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔发生。
  2. 解释二:并行是在不同实体上的多个事件,并发是在同一实体上的多个事件
  3. 解释三:在一台处理器上“同时”处理多个任务,在多台处理器上同时处理多个任务。如hadoop分布式集群

所以并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理性能,并发是与时间相关的。通过多线程实现并发,并行:

  1. 在CPU比较繁忙,资源不足的时候(开启了很多进程),操作系统只为一个含有多线程的进程分配仅有的CPU资源,这些线程就会为自己尽量多抢时间片,这就是通过多线程实现并发,线程之间会竞争CPU资源争取执行机会。
  2. 在CPU资源比较充足的时候,一个进程内的多线程,可以被分配到不同的CPU资源,这就是通过多线程实现并行。
  3. 至于多线程实现的是并发还是并行?上面所说,所写多线程可能被分配到一个CPU内核中执行,也可能被分配到不同CPU执行,分配过程是操作系统所为,不可人为控制。所有,如果有人问我我所写的多线程是并发还是并行的?我会说,都有可能。
  4. 不管并发还是并行,都提高了程序对CPU资源的利用率,最大限度地利用CPU资源。
  • 临界区

临界区,可以理解为公共的资源或者说共享数据。临界区具有保护性,也就是说,只能一个线程占用临界区,一旦一个线程占了临界区,另外一个线程是不予许再占用的,必须等线程释放了才行。

  • 同步(Synchronous)和异步(Asynchronous)

同步和异步的本质区别是是否需要等待,比如一个方法在执行,必须等前面一个方法程执行完成,才可以执行,这就是同步。如果不需要等上一个方法执行完成,并行或者并发执行,这就是异步调用。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值