Java Web并发访问的线程安全问题 浅浅的花香味﹌ 2022-04-18 01:14 200阅读 0赞 # Java Web并发访问的线程安全问题 # 2018年05月12日 02:02:52 [菜鸟级的IT之路][IT] 阅读数:68更多 个人分类: [JAVA~JavaWeb][JAVA_JavaWeb] ## 一、Servlet的线程安全问题 ## Java web服务器下,每个Servlet只有一个实例(即单例模式),导致有多个Http请求发给一个Servlet实例,每个请求是一个线程。如果Servlet有类变量或实例变量,那么该变量就变成了共享资源,当多个线程访问操作该变量时,就有可能存在安全隐患。例如,当一个Http请求在访问该变量的时候,另一个Http请求可能在修改它的值。 解决方法:在Servlet中不要定义类变量或实例变量,如果非定义不可,就需要为操作该变量的所有方法加synchronized修饰符,进行同步控制。 注意: 1. 在Servlet中可以定义常量 2. 如果定义的变量只用查询操作,可以不加同步控制 3. 被Servlet调用的类中(如值对象、领域模型类)中是否可以安全的使用实例变量?如果你在每次方法调用时新建一个对象,再调用它们的方法,则不存在同步问题。因为它们不是多个线程共享的资源,只有共享的资源才需要同步,而Servlet的实例对于多个线程是共享的。 ## 二、Struts并发访问的线程安全问题 ## 同Servlet一样,Struts中的Action也是单例的,所以多Http请求访问时,也存在线程安全问题。 解决方法:同Servlet ## 三、Spring并发访问的线程安全性问题 ## 和Struts一样,Spring的Controller默认是Singleton的(非线程安全的),这意味着每个request过来,系统都会用原有的instance去处理,这样导致了两个结果:一是我们不用每次创建Controller,二是减少了对象创建和垃圾收集的时间;由于只有一个Controller的instance,当多个线程调用它的时候,它里面的instance变量就不是线程安全的了,会发生窜数据的问题。 当然大多数情况下,我们根本不需要考虑线程安全的问题,除非在Controller中声明了实例变量。因此,我们在使用spring mvc 的contrller时,应避免在controller中定义类变量或实例变量。 如: 1. `public class Controller extends AbstractCommandController {` 2. `......` 3. `protected Company company;` 4. `protected ModelAndView handle(HttpServletRequest request,HttpServletResponse response,` 5. `Object command,BindException errors) throws Exception {` 6. `company = ................;` 7. `}` 8. `}` 在这里有声明一个变量company,这里就存在并发线程安全的问题。 如果控制器是使用单例形式,且controller中有一个私有的变量a,所有请求到同一个controller时,使用的a变量是共用的,即若是某个请求中修改了这个变量a,则在别的请求中能够读到这个修改的内容。。 有几种解决方法: 1、在Controller中使用ThreadLocal变量 2、在spring配置文件Controller中声明 scope=”prototype”,每次都创建新的controller。 注意:在Spring mvc中,如果dao、service也是单例的,要避免在Dao和Service类中建立类变量或实例变量。 ## 四、SpringMVC多线程环境中如何保证对象的安全性? ## [http://linapex.blog.163.com/blog/static/189237516201381493441799/][http_linapex.blog.163.com_blog_static_189237516201381493441799] 总结:多线程环境下如果访问单例对象,当对象内部有类变量或实例变量时,就可能存在安全性问题。 解决方法: 1.对操作共享变量的所用方法进行同步控制; 2.同步共享变量,例如Collections.synchronizedMap()可以同步共享的Map。 3.使用同步对象,例如ConcurrentMap、AtomicInteger等对象都是线程安全的,使用AtomicInteger可以统计系统的并发量。 ========================================================================================== 在web开发中,要关注由于并发访问所导致的对某一同一个值的修改,否则信息会造成泄漏servlet是在多线程环境下的。即可能有多个请求发给一个servelt实例,每个请求是一个线程。 struts下的action也类似,同样在多线程环境下。可以参考struts user guide: [http://struts.apache.org/struts-action/userGuide/building\_controller.html][http_struts.apache.org_struts-action_userGuide_building_controller.html] 中的Action Class Design Guidelines一节: Write code for a multi-threaded environment - Our controller servlet creates only one instance of your Action class, and uses this one instance to service all requests. Thus, you need to write thread-safe Action classes. Follow the same guidelines you would use to write thread-safe Servlets. 译:为多线程环境编写代码。我们的controller servlet指挥创建你的Action 类的一个实例,用此实例来服务所有的请求。因此,你必须编写线程安全的Action类。遵循与写线程安全的servlet同样的方针。 1.什么是线程安全的代码 在多线程环境下能正确执行的代码就是线程安全的。 安全的意思是能正确执行,否则后果是程序执行错误,可能出现各种异常情况。 2.如何编写线程安全的代码 很多书籍里都详细讲解了如何这方面的问题,他们主要讲解的是如何同步线程对共享资源的使用的问题。主要是对synchronized关键字的各种用法,以及锁的概念。 Java1.5中也提供了如读写锁这类的工具类。这些都需要较高的技巧,而且相对难于调试。 但是,线程同步是不得以的方法,是比较复杂的,而且会带来性能的损失。等效的代码中,不需要同步在编写容易度和性能上会更好些。 我这里强调的是什么代码是始终为线程安全的、是不需要同步的。如下: 1)常量始终是线程安全的,因为只存在读操作。 2)对构造器的访问(new 操作)是线程安全的,因为每次都新建一个实例,不会访问共享的资源。 3)最重要的是:局部变量是线程安全的。因为每执行一个方法,都会在独立的空间创建局部变量,它不是共享的资源。局部变量包括方法的参数变量。 struts user guide里有: Only Use Local Variables - The most important principle that aids in thread-safe coding is to use only local variables, not instance variables , in your Action class. 译:只使用用局部变量。---编写线程安全的代码最重要的原则就是,在Action类中只使用局部变量,不使用实例变量。 总结: 在Java的Web服务器环境下开发,要注意线程安全的问题。最简单的实现方式就是在Servlet和Struts Action里不要使用类变量、实例变量,但可以使用类常量和实例常量。 如果有这些变量,可以将它们转换为方法的参数传入,以消除它们。 注意一个容易混淆的地方:被Servlet或Action调用的类中(如值对象、领域模型类)中是否可以安全的使用实例变量?如果你在每次方法调用时 新建一个对象,再调用它们的方法,则不存在同步问题---因为它们不是多个线程共享的资源,只有共享的资源才需要同步---而Servlet和Action的实例对于多个线程是共享的。 换句话说,Servlet和Action的实例会被多个线程同时调用,而过了这一层,如果在你自己的代码中没有另外启动线程,且每次调用后续业务对象时都是先新建一个实例再调用,则都是线程安全的。 [IT]: https://me.csdn.net/WYpersist [JAVA_JavaWeb]: https://blog.csdn.net/WYpersist/article/category/7658605 [http_linapex.blog.163.com_blog_static_189237516201381493441799]: http://linapex.blog.163.com/blog/static/189237516201381493441799/ [http_struts.apache.org_struts-action_userGuide_building_controller.html]: http://struts.apache.org/struts-action/userGuide/building_controller.html
相关 Java并发问题:线程安全的ArrayList实例 在Java中,一个线程安全(thread-safe)的ArrayList实例可以通过实现`AbstractList`或其子类,如`CopyOnWriteArrayList`来创 爱被打了一巴掌/ 2024年09月18日 13:27/ 0 赞/ 3 阅读
相关 使用Java编写的并发问题——线程安全 在Java编程中,线程安全是一个非常重要的概念。当多个线程同时访问和修改一个对象时,如果这些操作没有正确地同步,就可能导致数据不一致或程序崩溃。 以下是一些保证线程安全的方法 Myth丶恋晨/ 2024年09月12日 15:18/ 0 赞/ 18 阅读
相关 并发编程:Java中的线程安全问题 在Java中,线程安全问题主要涉及到共享资源的并发访问可能引发的问题。以下是一些常见的线程安全问题: 1. **数据竞争**:多个线程同时访问和修改同一份数据,可能会导致数据 浅浅的花香味﹌/ 2024年09月10日 23:51/ 0 赞/ 20 阅读
相关 Java并发问题实例:线程安全的疑问 在Java编程中,线程安全是一个关键的概念。当一个变量或方法在其作用域内对多个线程都是可见且不会导致数据不一致时,我们称之为线程安全。 下面提供一个简单的例子来理解这个问题: 心已赠人/ 2024年09月06日 02:12/ 0 赞/ 13 阅读
相关 Java多线程并发问题:线程安全的实现 在Java编程中,线程安全主要是指多个线程同时访问共享资源时,不会出现数据不一致的情况。以下是一些线程安全的Java实现方法: 1. 同步(Synchronized): 梦里梦外;/ 2024年09月05日 16:54/ 0 赞/ 44 阅读
相关 java多线程高并发线程安全问题 在抢购之类的业务处理时,会出现超发之类的线程安全问题。 我个人想到的解决方法如下: 1. 采用数据库锁,悲观锁有效率低下问题,所以我推荐乐观锁,虽然会增大CPU开销,很多 客官°小女子只卖身不卖艺/ 2022年06月13日 03:27/ 0 赞/ 307 阅读
相关 Java并发编程---线程安全问题 1.线程安全的概念 当多个线程访问某一个类(对象或方法)时,这个类始终都能表现出正确的行为,那么这个类(对象或方法)就是线程安全的. synchronized:可以在任意对 谁践踏了优雅/ 2022年06月03日 08:54/ 0 赞/ 193 阅读
相关 解决线程并发安全问题 package cn.wlt.tickets; /\\ \ \ @作者: CarryWang \ @描述: 买票窗口 100张票 \ \/ publ 红太狼/ 2022年05月29日 02:14/ 0 赞/ 190 阅读
相关 Java Web并发访问的线程安全问题 Java Web并发访问的线程安全问题 2018年05月12日 02:02:52 [菜鸟级的IT之路][IT] 阅读数:68更多 个人分类: [JAVA~JavaWeb 浅浅的花香味﹌/ 2022年04月18日 01:14/ 0 赞/ 201 阅读
还没有评论,来说两句吧...