本次视频讲解了以下几个问题:

    一、线程实现模型
    用户态创建的模型与 操作系统的内核态模型对应关系

    1. 一对一 : java操作模型就是一对一,当我们使用new thread的时候就是创建了一个用户态模型,同时会在操作系统中创建一个内核态。优点是当用户态阻塞导致对应的内核态阻塞。但是不会影响其他线程的执行,同时在用户态阻塞后,会暂时挂起,这时候,将会转换为内核态挂起。这个转换很是消耗资源。这也是缺点之一。
    2. 多对一 : 多个用户态 对应一个内核态。这样一个用户态阻塞导致内核阻塞。然后与此内核态对应的用户态将都阻塞。优点是不需要转换
    3. 多对多: 以上两种的结合。

    二、jvm 内存模型 与 机器硬件的模型

    1> jvm
    包括两部分: 堆和 栈
    ———————————-
    栈1 栈2 栈3 —- 栈n

    1. 堆<br />-----------------------
    1. 栈中的数据是每个线程存储自己的局部变量的
    2. 堆中存储的是共享变量

    2> 机器硬件内存模型:
    ① cpu
    ② 寄存器
    ③ cach环城
    ④ 内存
    速度:1》2》3》4
    大小:4》3》2》1

    三、数据可见性问题
    由于java 的内存模型的特点。导致了数据可见性问题
    因为: 数据在 读取与写入的顺序如下
    读取:系统会 检查寄存器中是否存在 然后检查 缓存中是否存在 最后在检查 内存中。所以有三个位置存储值。这样在数据变更时候 例如 : a 从 1 => 2,系统会暂时将值2 放在缓存中 , 这时候另外一个线程来读取的时候读到值将会是 1 。因为内存 与 线程2 的 缓存和寄存器中的值是没有来得及改变 。
    所以导致了 数据的错误。

    另外问题: 由于指令重排,也会导致 内存值在没有变化时候后就会被其他线程使用,然而这个值其实应该已经被线程1 改变了才对。

    解决这个问题:可以是volatile 关键字。。

    1. 这个修饰符的作用是: 将读取数据 时候 直接读取内存数据,和 写入时候直接写入内存。这样在使用时候将会避免数据的可见性问题。同时这个关键字也会 干涉指令重排机制,使得,先操作后读取 为宗旨的执行,也就是 happen-before 原则。
    1. 另外也可以使用 synchrnized 关键字。

    被此关键字修饰的代码块,将会是原子性操作。并且内部的所有变量都将会有 volatile 特性。既:直接操作内存进行 读或者写,所以有性能上的损失。

    三、 java 线程的 user 线程与 deam 线程 ,用户线程与守护线程

    1. 用户线程 执行完毕后,守护线程会自动停止。
    2. 主线程结束后,用户线程(另起的用户线程)会指继续执行,直到完成。主线程不会影响 其他的用户线程
    3. 学习到的命令: jsp 查看所有线程
    4. jstack 线程编号 : 查看线程的详细内容

    (找时间去查找 ps 与 jstack 命令的用法)

    以上是第二课的大概内容。。。