线程是操作系统中最小的工作业务单元,在执行业务逻辑时,线程会把主内存中的变量值copy到线程自己的工作内存中,后续发生的读写操作都是对工作内存中的副本变量进行的。 由于线程什么时候将工作内存中的副本变量更新到主内存的时机并不是固定的,线程在读取主内存和刷新主内存变量的操作也并非原子性的,所以在多线程的时候,就会引起并发问题。下面的几种场景介绍了工作内存和主内存之间刷新时机。
将主内存中的值读取到工作内存
1 当工作内存中没有主内存的变量副本时,会将主内存中的值读取到工作内存;
2 当线程获取到锁时
3 线程发生上下文切换时,比如调用wait(), sleep()等阻塞方法再到线程恢复运行,此时线程就进行了一次上下文切换,值得一提的是,调用System.out等相关方法引起的I/O阻塞,也会刷新工作线程中的变量。
4 当变量被volatile修饰引起的副本失效时
5 说的是当执行该线程的cpu有空闲时,他会去主存读取一下共享变量的值来更新线程工作内存中的值
将工作内存中的值更新到主内存
1 把一个从执行引擎接收的值赋给工作内存的变量后,立即同步到主内存。但是这两个操作并不保证原子性。中间可能有其他操作。
2 线程在释放锁之前会将工作内存中的变量更新到主内存
3 修改volatile修饰的变量时 volatile保证了内存可见性,当修改被volatile修饰的变量后,会强制将工作内存中的值更新到主内存,并且使其他线程工作内存中缓存了该变量的副本失效。