Java中,两个请求同时访问一个action或method,代码的执行顺序是怎么样的
首先看文章之前你可以在脑海中模拟一下,两个请求并发访问一个方法,从浏览器到后台的大致流程是怎么样的,模拟的越详细越好。
我相信很大一部分人可能都会被这个问题难住,不管是刚毕业的大学生,还是工作两三年的朋友们。
可能我们平时太多的关注业务逻辑,关注各种炫酷的框架,亦或者是公司太忙,忙到我们没时间成长等等等,从而忽略了这些最基础的东西。不过可能正是因为这些最基础的东西,才是我们为什么薪资比别人低了一点,为什么机会比别人少了一点,为什么差距和别人越来越大。
学而不思则罔,思而不学则殆。
- 这个问题其实分两步
- 第一步是用户点击页面,并发送请求到服务器的步骤,这个步骤很复杂,涉及到网络协议很多东西,我们暂且不讲。
- 第二步就是服务器收到请求,我们代码执行的过程,我们具体说一下这一步。
如下图这个简单的方法
有两个请求并发访问,也就是说有两个线程同时准备进入方法printA()。那么问题来了
是线程1先进入方法执行完毕后再让线程2进入执行吗。
不是的,是两个线程同时去执行这一段代码
那有同学可能会问了,如果两个线程同时进入这个方法,
线程1执行到a = a + 10;此时a的值为11,
然后线程2进入方法执行int a = 1; 那线程1打印出来a是不是就变成1了。
不是的,线程1打印a还是为11,为什么呢,因为a是定义在方法里面的,是局部变量。
然后每个线程是不是都有一个私有的本地内存(Local Memory),这个私有本地内存是不是存放这个局部变量的,答案是肯定的,既然赋值操作都是在我自己的地盘弄的,那肯定不会影响到别人。
但是如果我在这个类中加入一个全局变量,如下图
两个线程同时进入这个方法,那输出的c肯定是不一样的,为什么呢,相信你已经猜到了,没错。
这是因为线程之间的共享变量存储在主内存(Main Memory)中,变量c是全局变量,会放在主存中。
类初始化的时候全局变量会被加载到主存中,线程1需要对c赋值计算的时候,从主存中拷贝一个c的副本,放到自己的私有内存中,计算完毕后c的值发生了变化,回写到主存中,这时候线程2需要对c赋值计算了,再把c拷贝一个副本到自己的私有内存里,计算完毕后,再回写到主存中,最后的结果就是对c进行了两次操作。其实这个过程就是线程之间的通讯过程
如下草图
- 好了,差不多到这里这个简易的流程就算是结束了。涉及到了几个知识点,线程内存模型,全局变量和成员变量的区别。
- 写这篇文章的目的是想帮助对这一块概念比较模糊的同学,大家都知道线程的定义,变量的定义,但是结合在一起可能会迷糊一点,这里借一个简单的小例子可以帮大家把学到的东西串起来。
- 知其然,知其所以然,才可以更好的敲代码。