线程学习_03线程相关概念

2018-02-18  本文已影响12人  冉桓彬
物理内存 :

  由于计算机的存储设备与处理器的运算速度有几个数量级的差距, 所以现代计算机系统都不得不加入一层读写速度尽可能接近处理器运算速度的高速缓存来作为内存与处理器之间的缓存: 将运算需要使用到的数据复制到缓存中, 让运算能快速进行, 当运算结束后再从缓存同步回内存中, 这样处理器就无须等待缓慢的内存读写了;

缓存一致性 :

  在多处理器系统中, 每个处理器都有自己的高速缓存, 而它们又共享同一主内存. 当多个处理器的运算任务都涉及同一块主内存区域时, 将可能导致各自的缓存数据不一致.


image.png
指令重排序 :

  为了使得处理器内部的运算单元能尽量被充分利用, 处理器可能会对输入代码进行乱序执行优化, 处理器会在计算之后将乱序执行的结果重组, 保证该结果与顺序执行的结果是一致的, 但并不保证程序中各个语句计算的先后顺序与输入代码的顺序一致, 因此, 如果存在一个计算任务依赖另一个计算任务的中间结果, 那么其顺序性并不能靠代码的先后顺序来保证;

java内存模型 :

  1、java内存模型的主要目标是定义程序中各个变量的访问规则, 此处的变量包括了实例字段, 静态字段和构成数组对象的元素, 但不包括局部变量与方法参数, 因为后者是线程私有的, 不会被共享, 不会存在竞争的问题;
  2、java内存模型规定了所有的变量都存储在主内存中. 每条线程还有自己的工作内存, 线程的工作内存中保存了该线程使用到的变量的主内存副本拷贝, 线程对变量的所有操作(读取, 赋值等)都必须在工作内存中进行, 而不能直接读写主内存中的变量.
  3、不同的线程之间也无法直接访问对方工作内存中的变量, 线程间变量值得传递均需要通过主内存来完成.
  4、工作内存对应虚拟机栈中的部分区域, 主内存对应于物理硬件的内存;


image.png
内存间交互 :

  主内存与工作内存之间具体的交互协议 : java内存模型中定义了以下8种操作来完成, 一个变量在主内存和工作内存之间的交互的实现细节, 虚拟机实现时必须保证下面提及的每一种操作都是原子的、不可再分的;

volatile :

  1、可见性 : 保证变量对所有线程可见, 当一条线程修改了这个变量的值, 新值对于其他线程来说是可以立即得知的;
  2、禁止指令重排序 : 指令重排序是指CPU采用了允许将多条指令不按程序规定的顺序分开发送给各相应电路单元处理.
  分别用两段常见代码来阐述volatile这两个特性 :

可见性(但不能保证原子性):
public class Instance {
    private static int i;
    public static void increase() {
        i++;
    }
}

  上面代码实际要分为以下几个步骤:

1. 将变量i读取到工作内存中;
2. int var = i + 1;操作赋值给var变量;
3. var变量再赋值给i;
4. i回写到主内存中;

  所以当多个内存同时调用increase()方法时, 可能线程_1执行到步骤2时, 线程_2也执行到步骤2, 就会导致increase()被两个线程分别调用一次, 但是i实际为1的线程;

禁止指令重排序 :
public class Instance {
    private static Instance instance;
    public static Instance getInstance() {
        if (instance == null) {
            synchronized(Instance.class) {
                if (instance == null ) {
                    instance  = new Instance();
                }
            }
        }
        return instance;
    }
}

  instance = new Instance()可以分为以下几个步骤 :

  但是由于指令重排序, 上述步骤也可能实际执行顺序为1_2_4_3;按照这个顺序, 当线程1执行到步骤4时, 线程2调用getInstance()方法发现instance此时已经被赋值一个引用 != null, 直接走return方法, 但是此时instance所指向的Instance对象并没有初始化完成, 即内部变量都还是默认值;

线程的实现 :

实现线程主要有3种方式 : 使用内核线程、使用用户线程和使用用户线程加轻量级进程混合;
1、使用内核线程实现 :
  

线程的状态 :

  java语言定义了6种线程状态, 在任意一个时间点, 一个线程只能有且仅有其中的一个状态:

1. 没有设置Timeout参数的Object.wait()方法;
2. 没有设置Timeout参数的Thread.join()方法;
3. LockSupport.park()方法;
1. Thread.sleep()方法;
2. 设置了Timeout参数的Object.wait()方法;
3. 设置了Timeout参数的Thread.join()方法;
4. LockSupport.parkNanos()方法;
5. LockSupport.parkUnitl()方法;
上一篇 下一篇

猜你喜欢

热点阅读