大概看了一下tomcat实例化servlet的源代码,和spring mvc的DispatcherServlet的源代码,现在问题来了,spring的DispatcherServlet不是线程安全的.
我看的源代码版本是:tomcat 7.0.57 spring 3.0.5. 重点查看了org.apache.catalina.core.StandardWrapper和DispatcherServlet的源代码。
为什么说DispatcherServlet不是线程安全(有可能不可见)现在问题如下:
StandardWrapper是Servlet的包装类,其内有个protected volatile Servlet instance = null;属性,存放的servlet的实例,这个实例使用标准的双检查锁来实例化和初始化,初始化的时候在synchronized(this)的同步块内,调用 servlet.init(facade);因为在synchronized同步块内,其可以保证在同步块结束后所有对成员变量的修改都会刷新(写回)到主内存。
说到上面的servlet.init(facade);我们现在来切换到DispatcherServlet类,这个类继承于FrameworkServlet -> HttpServletBean -> HttpServlet,DispatcherServlet的initStrategies(ApplicationContext context),也是在servlet.init(facade)方法内的调用,因此也在synchronzied同步块内调用,因此其可以保证initStrategies方法对DispatcherServlet实例成员变量的修改后刷新到主内存。
我们再来看看DispatcherServlet的一些成员变量的声明,都是普通的声明,前都没有用final和volatile修饰:
/** MultipartResolver used by this servlet */
private MultipartResolver multipartResolver;
/** LocaleResolver used by this servlet */
private LocaleResolver localeResolver;
/** ThemeResolver used by this servlet */
private ThemeResolver themeResolver;
/** List of HandlerMappings used by this servlet */
private List handlerMappings;
/** List of HandlerAdapters used by this servlet */
private List handlerAdapters;
/** List of HandlerExceptionResolvers used by this servlet */
private List handlerExceptionResolvers;
/** RequestToViewNameTranslator used by this servlet */
private RequestToViewNameTranslator viewNameTranslator;
/** FlashMapManager used by this servlet */
private FlashMapManager flashMapManager;
/** List of ViewResolvers used by this servlet */
private List viewResolvers;
现在就要问题的实质了,doDispatch(HttpServletRequest request, HttpServletResponse response)方法,在没有任何同步的情况下,使用上面这些属性的实例,可见性能保证吗?
spring的DispatcherServlet不是线程安全的.
猜你喜欢
转载自neptune.iteye.com/blog/2269533
今日推荐
周排行