What JMM (Java Memory Model) that? Why concurrency?

1, computer

  First, we need to explain the model of the computer: Modern computer model is based - von Neumann computer model

  We do not control the input and output devices, the most important is the interaction between the calculator and the intermediate memory, i.e. access between the CPU and main memory, the number of memory.

  You will see there is a flow of IO bus carrying data, so the CPU to interact with the disk IO will be by bus, but on some other data bus IO in circulation, such as monitor, mouse, keyboard, etc., and now the CPU widespread computational speed in GHz, but our memory output is MB, which greatly affected the CPU, because each taking the number of IO to go through the middle, will inevitably affect the IO, the CPU has three cache, L1, L2, L3, the instruction cache stores those set anything. As shown below:

CPU reads the memory data process
  XX CPU to take the value of the register, only one step: read directly.
  CPU To take a value of L1 cache, takes 1-3 steps (or more): the cache line lock, bring to a data, unlock, if not locked to slow.
  CPU to take a value of L2 cache, the L1 cache in the first to take, among L1 does not exist in the L2, L2 start lock, after the lock to copy the data in L2 to L1, then L1 is a read process, step 3 above, and then unlock.
  Cache CPU fetches L3 is the same, but first by L3 to L2 copied, copied from the L2 to L1, from L1 to the CPU.
  Memory CPU fetches the most complex: the controller notifies the memory bus bandwidth occupied, the memory lock notification, initiates a memory read request, wait for a response, response data is saved to L3 (if not to the L2 of), and then from the L3 / 2 to L1, then after release from L1 to CPU bus lock.
  Cache coherency problem: When there are multiple processors, how to ensure data between the CPU1 and CPU2 is consistent, in order to ensure consistency of the data, you need to access the cache at the same time, to follow some protocols such as MESI, who finally cache is final.

2. What is the thread

  现代操作系统在运行一个程序时,会为其创建一个进程。例如,启动一个Java程序,操作系统就会创建一个Java进程。现代操作系统调度CPU的最小单元是线程,也叫轻量级进程(Light Weight Process),在一个进程里可以创建多个线程,这些线程都拥有各自的计数器、堆栈和局部变量等属性,并且能够访问共享的内存变量。处理器在这些线程上高速切换,让使用者感觉到这些线程在同时执行。线程的实现可以分为两类:
  1、用户级线程(User-Level Thread)
  2、内核线线程(Kernel-Level Thread)
  用户线程:指不需要内核支持而在用户程序中实现的线程,其不依赖于操作系统核心,应用进程利用线程库提供创建、同步、调度和管理线程的函数来控制用户线程。另外,用户线程是由应用进程利用线程库创建和管理,不依赖于操作系统核心。不需要用户态/核心态切换,速度快。操作系统内核不知道多线程的存在,因此一个线程阻塞将使得整个进程(包括它的所有线程)阻塞。由于这里的处理器时间片分配是以进程为基本单位,所以每个线程执行的时间相对减少。
  内核线程:线程的所有管理操作都是由操作系统内核完成的。内核保存线程的状态和上下文信息,当一个线程执行了引起阻塞的系统调用时,内核可以调度该进程的其他线程执行。在多处理器系统上,内核可以分派属于同一进程的多个线程在多个处理器上运行,提高进程执行的并行度。由于需要内核完成线程的创建、调度和管理,所以和用户级线程相比这些操作要慢得多,但是仍然比进程的创建和管理操作要快。大多数市场上的操作系统,如Windows,Linux等都支持内核级线程。

 

   我们每创建一个线程,jvm都会帮我们在内核空间创建一个线程,这样就避免了jvm来管理线程使操作系统不知道线程的存在,只知道jvm这一个进程,所以一旦jvm中的线程堵塞,CPU是不会进行上下文切换的,导致整个jvm进程都会堵塞。

三、为什么用到并发?并发会产生什么问题?

  并发编程的本质其实就是利用多线程技术,在现代多核的CPU的背景下,催生了并发编程的趋势,通过并发编程的形式可以将多核CPU的计算能力发挥到极致,性能得到提升。除此之外,面对复杂业务模型,并行程序会比串行程序更适应业务需求,而并发编程更能吻合这种业务拆分 。
  即使是单核处理器也支持多线程执行代码,CPU通过给每个线程分配CPU时间片来实现这个机制。时间片是CPU分配给各个线程的时间,因为时间片非常短,所以CPU通过不停地切换线程执行,让我们感觉多个线程是同时执行的,时间片一般是几十毫秒(ms)。
  并发不等于并行:并发指的是多个任务交替进行,而并行则是指真正意义上的“同时进行”。实际上,如果系统内只有一个CPU,而使用多线程时,那么真实系统环境下不能并行,只能通过切换时间片的方式交替进行,而成为并发执行任务。真正的并行也只能出现在拥有多个CPU的系统中。
  并发的优点:
    1充分利用多核CPU的计算能力;
    2方便进行业务拆分,提升应用性能;
   并发产生的问题:
    1.高并发场景下,导致频繁的上下文切换
       2.临界区线程安全问题,容易出现死锁的,产生死锁就会造成系统功能不可用
  CPU通过分配时间片来每次循环任务,每次需要切换到下一个任务时,都会保存上一个任务的结束状态,以便切换回来可以在加载这个任务,所以任务从保存到再加载的过程就是一次上下文切换。

四、什么是JMM模型?

  JMM并不真实存在,只是一种规范,通过这种规范来让定义程序中各个变量的访问方式。JVM运行程序的实体是线程,而每个线程创建时JVM都会为其创建一个工作内存(有些地方称为栈空间),用于存储线程私有的数据,而Java内存模型中规定所有变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问,但线程对变量的操作(读取赋值等)必须在工作内存中进行,首先要将变量从主内存拷贝的自己的工作内存空间,然后对变量进行操作,操作完成后再将变量写回主内存,不能直接操作主内存中的变量,工作内存中存储着主内存中的变量副本拷贝,前面说过,工作内存是每个线程的私有数据区域,因此不同的线程间无法访问对方的工作内存,线程间的通信(传值)必须通过主内存来完成

  JMM是围绕原子性,有序性、可见性展开
JMM-同步八种操作介绍
  (1)lock(锁定):作用于主内存的变量,把一个变量标记为一条线程独占状态
  (2)unlock(解锁):作用于主内存的变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定
  (3)read(读取):作用于主内存的变量,把一个变量值从主内存传输到线程的工作内存中,以便随后的load动作使用
  (4)load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中
  (5)use(使用):作用于工作内存的变量,把工作内存中的一个变量值传递给执行引擎
  (6)assign(赋值):作用于工作内存的变量,它把一个从执行引擎接收到的值赋给工作内存的变量
  (7)store(存储):作用于工作内存的变量,把工作内存中的一个变量的值传送到主内存中,以便随后的write的操作
  (8)write(写入):作用于工作内存的变量,它把store操作从工作内存中的一个变量的值传送到主内存的变量中
  如果要把一个变量从主内存中复制到工作内存中,就需要按顺序地执行read和load操作,如果把变量从工作内存中同步到主内存中,就需要按顺序地执行store和write操作。但Java内存模型只要求上述操作必须按顺序执行,而没有保证必须是连续执行。

 

Guess you like

Origin www.cnblogs.com/guoxiaoyu/p/11242876.html