一、可见性
直接感受下吧!直接上代码。
@Controller@RequestMapping("/factory")public class MachineFactoryController {// 静态变量位于堆内存中,所有线程共享private static int i = 0;@RequestMapping("/access")@ResponseBodypublic Long access(@RequestParam(name = "provinceId") Long provinceId, @RequestParam(name = "cityId") Long cityId) {int loopCount = 10;for (int j = 0; j < loopCount; j++) {// 模拟其他业务}i = i + 1;int step = 10;if (i % step == 0) {LOGGER.info("{}", i);}return cityId;}@RequestMapping("/monitor")@ResponseBodypublic Integer monitor() {LOGGER.info("{}", i);return Integer.valueOf(i);}}
第一步,启动jmeter开启一个线程组,共有100个线程。使用这个线程组发起100次/factory/access请求,理论上,只要这100个线程执行完毕,i的最终结果是100。但实际上,并不是。
第二步,使用谷歌浏览器直接访问/factory/monitor,打印堆内存中变量i的值,神奇的事情发生了,可以发现是98,这是问什么?
第三步,思考造成i最终结果不正确的原因是什么?
多线程环境下,每个线程同时访问共享资源时,一定存在线程可见性问题。
第四步,如何解决可见性问题?
其实,就此场景而言,使用volatile虽然解决了可见行问题,但是解决不了非原子操作的问题。有两种解决方案。
a、对共享资源加锁,比如说synchronize。
b、使用线程安全的类型,比如说AtomicInteger类。
