spring 中的单例模式在并发的情况下是怎么保证数据不会混乱的??
首先我们知道Spring 中controller、service、dao都为单例模式(注:默认状态)。
既然是单例,那么在并发的情况下,会发生什么?
废话不多说,看代码。
后台:
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserServiceI userService;
private int i;
@POST
@RequestMapping("test.do")
@ResponseBody
public Result test(User user) {
System.out.println(user.getUserName()+":进入方法");
i++;
System.out.println("开始阻塞");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("阻塞结束");
System.out.println("i="+i);
System.out.println("此时UserName:"+user.getUserName());
return null;
}
}
前台:
<div>
<fieldset>
<form action="<%=basePath%>user/test.do" method="post">
<input name="userName"><br>
<input type="submit" value="提交">
</form>
</fieldset>
</div>
两台电脑:一个输入1,一个输入2,点击提交,提交时间间隔1秒左右即可。
控制台输出:
1:进入方法
开始阻塞
2:进入方法
开始阻塞
阻塞结束
i=2
此时UserName:1
阻塞结束
i=2
此时UserName:2
看到,成员变量 i 受到了并发的影响,而我们表单提交的userName参数,并未收到并发的影响。
再测,继续提交表单,看到 i 的值一直在自增,对于我来说这是一个吓人的发现,作了这么久的程序员,刚发现这个问题。。。多久就不透露了,丢人。。
下面是来自博客的答案:
成员方法也是共享的,为什么就不会出现问题呢?
==================================================
java 里,每个线程都有自己独享的空间,也就是栈内存。线程在调用方法的时候,会创建一个栈帧。也就是说调用一个方法的时候,也就是一个栈帧的入栈过程,该方法执行完毕,栈帧也就出栈了。
换句话讲,成员方法对于每个线程事实上是私有的,而不是你表面看上去的那样是 "共享" 的。
那么为什么成员变量会出问题呢?
==================================================
如你所知道的,每个新建对象都存放在堆中,每个持有该对象引用的线程,都可以访问到它(只要你有那个权限)。
这也就是说,成员变量对于每个线程,事实上是共享的。
而service层呢?dao呢?
经过测试,与controller结论相同。
转载地址:https://blog.csdn.net/zhangweijie_cn/article/details/70212630