计算机执行程序的时候每条指令都是在 CPU 中执行的,而执行指令过程中,势必涉及到数据的读取和写入。由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这时就存在一个问题,由于 CPU 执行速度很快,而从内存读取数据和向内存写入数据的过程跟 CPU 执行指令的速度比起来要慢的多,因此如果任何时候对数据的操作都要通过和内存的交互来进行,会大大降低指令执行的速度。因此在 CPU 里面就有了高速缓存。
当程序在运行过程中,会将运算需要的数据从主存复制一份到 CPU 的高速缓存当中,那么 CPU 进行计算时就可以直接从它的高速缓存读取数据和向其中写入数据,当运算结束之后,再将高速缓存中的数据刷新到主存当中。
1 2 3 4 5 6
classSharedObj { // Changes made to sharedVar in one thread // may not immediately reflect in other thread staticintsharedVar=6; }
ThreadreaderThread=newThread(() -> { inttemp=0; while (true) { if (temp != num) { temp = num; System.out.println("reader: value of num = " + num); } } });
ThreadwriterThread=newThread(() -> { for (inti=0; i < 5; i++) { num++; System.out.println("writer: changed value to = " + num); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }
// 退出程序,否则readerThread会一直等 System.exit(0); });
readerThread.start(); writerThread.start(); } }
输出如下
1 2 3 4 5 6
reader: value of num = 1 writer: changed value to = 1 writer: changed value to = 2 writer: changed value to = 3 writer: changed value to = 4 writer: changed value to = 5
没加 volatile 的时候 reader 只读到 0-1 的变化。
接下来修改代码
1
volatilestaticint num;
输出如下
1 2 3 4 5 6 7 8 9 10
writer: changed value to = 1 reader: value of num = 1 writer: changed value to = 2 reader: value of num = 2 writer: changed value to = 3 reader: value of num = 3 writer: changed value to = 4 reader: value of num = 4 writer: changed value to = 5 reader: value of num = 5
可以看到输出 reader 可以读到 num 的变化,volatile 指示编译器,这个变量是共享的且不稳定,每次要到主程序中读取。