Java线程整理(一)

117 阅读2分钟

根据某士bin的直播课程的,技术总结。

  • 首先从硬件层面上进行科普。为了提高cpu运行效率。cpu厂商采取了两种形式。
  1. 三级缓存,对内存数据进行记录,便于快速读取。
  2. 64Byte的数据集,一次性缓存一定长度的数据量。 而硬件层面上,统一有着“缓存一致性协议”,英特尔的架构协议采用MESI(梅西协议),是其中一种。
  • 目的在于,当cpu不同核心读取了同一条数据集的时候,在进行操作后,要通知另外的核心,我改了你正在使用数据集合里的一个值,于是它们需要统一数据。而这个过程,是需要时间的,降低了速度。 那么回到软件编程上。为了减少多线程的缓存一致性情况的发生,会在一条数据的后面,增加7个long类型的数据,一个long,8Byte,正是因为缓存集合的长度为64Byte。这是考虑了可见性,知道了剩余的废数据是什么。
  • 接下来是线程的第二条,有序性。首先要知道汇编语言对于java一个对象生成的原理,当我们int m = 1;的时候,首先,是生成了一个空间,然后进行数据计算,得到的结果,与m相关联。但在这过程中会出现“指令重排”的情况,先进行了关联,再进行计算。从结果角度上是没有问题的。得到了 m = 1的结果。但是如果是多线程的判断。比如常见的DCL(double check lock)的多线程。
if(int m == null){
        syconize(){
        int m== null;
        }
}

可能因为指令重排的问题,m=0,还没等于11。的时候,被使用了。导致数据异常。所以这种情况下,需要对DCL进行valetile多线程限制。

  • 同样,大多数开源软件的多线程,也没有考虑到线程的有序性,直接在构造方法里面启动,会导致线程得到的值不正确。解决方法,额外写一个启动线程的方法。也不要用死循环监听多线程,要回调函数,避免因为线程顺序变化,而导致结果不一致