HttpSession的线程安全问题及注意事项

  1. HttpSession session =  request.getSession();
  2. List<Product> list = session.getAttribute("productCart");
  3. myService.save(list); // 保存购物车数据到数据库

这个对象会被多次使用,也会被同一个用户的多个页面使用,所以他对于系统来说是线程 不安全 的。 

比如用户在从产品列表里面选择产品,这面选择3种,他点了查看购物车 
该用户还开了另一个页面,继续选择产品。 

此时,在显示购物车的页面,有可能运行在一半时,其已经选择的产品列表,并另一个页面的操作修改了。所以显示的产品数量有可能并不是3种。 

因为session需要维持当前用户的信息,所以其在多个线程里是共享的。所以是线程不安全的。 


不过,这个是表面现象,我们只要正确使用事务,保证数据的准确性,表面的问题可以不用管它。 

我们可以把session里面的数据另外保存到一个新的数据对象里,这个对象不再因为session的改变而出现变动。这个对象传递给业务层进行事务处理,保证数据级别的准确。 

千万不要把session,或者 session里面的对象直接传递给业务层,因为你的业务处理一半时,同样可能出现session对象被改变的情况。有可能造成重要数据出现偏差。 
举例:  

session 对应三个产品, 
事务里面循环了产品,并计算了总价格, 
计算完毕,准备保存时,session变了,产品变成了4个。 
此时开始保存。产品保存了4个,可总价格却还是3个的。 

出现了数据不一致。 

修改后的例子  
session 对应三个产品 
重新生成一个产品对象数组,把session数据复制过来,然后传递给业务层 
事务里面循环计算总价格 
计算完毕,此时session变了,但并不影响我们这个新的产品数组对象 
保存,三个产品,价格也正确。 
  1. HttpSession session =  request.getSession();
  2. List<Product>  list = session.getAttribute("productCart");
  3. List<Product> listNew = new ArrayList<Product>();
  4. Product pNew;
  5. for(Product p : list){
  6.   pNew = new Product();
  7.   pNew.setProductId(p.getProductId());
  8.   // 其它的复制参数的语句
  9.   listNew.add(pNew); // 保存到新的列表里面
  10. }
  11. myService.save(listNew); // 保存购物车数据到数据库,这个是安全的

总结: 
有些线程安全问题是很隐蔽的,等你出了问题,很可能根本不认为会是那里出的问题。记住一点,Java里面的对象传递的是对象的引用,只要2个地方用了相同的引用,则其它地方的变动,这一面也会变动。

原文: http://www.java2000.net/p9667
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值