为什么多线程代码可能会出现问题
现代计算机都为了追求更快的运行,对其做了很多的优化,但是CPU,内存,IO三者还是有很大的差距,为了提高CPU的效率,增加CPU的缓存,操作系统采用了分时复用,编译器增加了指令优化。这些方式虽然增加了CPU执行的效率,但是对于多线程而言,也增加了可见性,原子性,有序性等问题.
1.可见性
对于多核的计算机,每个CPU都有自己的缓存,数据都是先读取到CPU本地缓存,更新完后再把数据写入到CPU本地缓存,而把缓存中的数据刷新到内存中的时间是不确定的,这样就会导致每个线程读取的数据是不一样的,这就是可见性问题。
2.原子性
操作系统为了保证cpu执行的效率,采用了分时复用来执行操作,每个进程都可以执行一段时间,然后切换为其它线程来执行
分析count += 1
分析count += 1,如果有线程切换,会带来的问题,count+=1这个语句在操作系统层面会变成三条指令来执行:
指令 1:首先,需要把变量 count 从内存加载到 CPU 的寄存器
指令 2:之后,在寄存器中执行 +1 操作
指令 3:最后,将结果写入内存(缓存机制导致可能写入的是 CPU 缓存而不是内存)
操作系统的任务,可能发生在任何一条指令执行完,所以多个线程可能有如下的执行顺序,会发现执行结果是1,而不是2
3.有序性
现在CPu都是流水线执行,为了提高CPU的执行效率,编译器对程序都做了优化,程序运行的顺序不一定和我们写的代码顺序一样,例如程序中:“a=1;b=2;”编译器优化后可能变成“b=7
a=6”,程序执行的结果虽然没有变化,但是在多线程执行的场景中,可能会出现不正确的结果.
所以解决多线程的问题就是解决可见性,原子性,有序性的问题