Java的内存模型JMM

Java的内存模型JMM(Java Memory Model)JMM主要是为了规定了线程和内存之间的一些关系。根据JMM的设计,系统存在一个主内存(Main Memory),Java中所有实例变量都储存在主存中,对于所有线程都是共享的。每条线程都有自己的工作内存(Working Memory),工作内存由缓存和堆栈两部分组成,缓存中保存的是主存中变量的拷贝,缓存可能并不总和主存同步,也就是缓存中变量的修改可能没有立刻写到主存中;堆栈中保存的是线程的局部变量,线程之间无法相互直接访问堆栈中的变量。根据JMM,我们可以将论文中所讨论的Servlet实例的内存模型抽象为下图所示的模型。

Servlet的线程安全问题

Servlet的线程安全问题主要是由于实例变量使用不当而引起的,这里以一个现实的例子来说明。

/**
* 模拟用户AB在同时执行不同的动作
* 先执行 http://localhost:8080/concurrent?username=A&action=play
* 稍后执行 http://localhost:8080/concurrent?username=B&action=eat
*/
public class Concurrent extends HttpServlet {
private static final long serialVersionUID = 1L;
private String action = "";//动作
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
String username = request.getParameter("username");
action = request.getParameter("username");
Thread.sleep(5000); //为了突出并发问题,在这设置一个延时
//如果不出意外,应该用户AB都在吃饭
System.out.println("用户:"+username+"在"+action);
} catch (Exception e) {
}
}
}

Struts1

首先,明确一点Sturts1 action是单例模式,线程是不安全的。Struts1使用的ActionServlet是单例的,既然是单例,当使用实例变量的时候就会有线程安全的问题。所有一般在开发中试禁止使用实例变量的。

Struts2

struts2使用的是actionContext,都是使用里面的实例变量,让struts2自动匹配成对象的。每次处理一个请求,struts2就会实例化一个对象,这样就不会有线程安全的问题了。

需要注意的是,如果struts2+spring来管理注入的时候,不要把Action设置成单例,否则会出问题的。当然现在很少有项目使用struts2了。

SpringMVC

SpringMVC的controller默认是单例模式的,所以也会有多线程并发的问题。

总结

  • servlet Struts1 SpringMvc 是线程不安全的,当然如果你不使用实例变量也就不存在线程安全的问题了。

  • Struts2 是线程安全的,当然前提情况是,Action 不交给 spring管理,并且不设置为单例。

  • SpringMvc 的 Bean 可以设置成多例变成线程安全,但是一定程度上回影响系统性能。

jmm 和线程安全的更多相关文章

  1. 【Java线程】Java内存模型总结

    学习资料:http://www.infoq.com/cn/articles/Java-memory-model-1 Java的并发采用的是共享内存模型(而非消息传递模型),线程之间共享程序的公共状态, ...

  2. (转)【Java线程】Java内存模型总结

    Java的并发采用的是共享内存模型(而非消息传递模型),线程之间共享程序的公共状态,线程之间通过写-读内存中的公共状态来隐式进行通信.多个线程之间是不能直接传递数据交互的,它们之间的交互只能通过共享变 ...

  3. JMM随笔

    What? Java内存模型(Java Memory Model,JMM)主要是为了规定了线程和内存之间的一些关系. 根据JMM的设计: 系统存在一个主内存(Main Memory),Java中所有变 ...

  4. 深入理解JMM(Java内存模型) --(三)顺序一致性

    数据竞争与顺序一致性保证 当程序未正确同步时,就会存在数据竞争.Java内存模型规范对数据竞争的定义如下: 在一个线程中写一个变量, 在另一个线程读同一个变量, 而且写和读没有通过同步来排序. 当代码 ...

  5. Java线程之Java内存模型(jmm)

    一.Java内存模型(jmm) 线程通信 消息传递 重排序 顺序一致性 Happens-Before As-If-Serial

  6. Java线程之基础

    Java内存模型(jmm) 线程通信 消息传递 重排序 顺序一致性 Happens-Before As-If-Serial 一.线程的生命周期及五种基本状态 线程生命周期:新建.就绪.运行.阻塞.死亡 ...

  7. Java并发指南2:深入理解Java内存模型JMM

    本文转载自互联网,侵删   一:JMM基础与happens-before 并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实 ...

  8. 并发和多线程(二)--启动和中断线程(Interrupt)的正确姿势

    启动线程: 从一个最基本的面试题开始,启动线程到底是start()还是run()? Runnable runnable = () -> System.out.println(Thread.cur ...

  9. Java并发读书笔记:JMM与重排序

    目录 Java内存模型(JMM) JMM抽象结构 重排序 源码->最终指令序列 编译器重排序 处理器重排序 数据依赖性 as-if-serial happens-before happens-b ...

随机推荐

  1. jQuery弹性展开收缩菜单插件gooey.js

    分享一款基于jQuery弹性展开收缩菜单插件gooey.js.这是一款基于gooey.js插件实现的弹性菜单特效代码.效果图如下: 在线预览   源码下载 实现的代码. html代码: <hea ...

  2. JedisConnectionPool scala

    /** * Created by lq on 2017/8/29. */ object JedisConnectionPool { val config = new JedisPoolConfig() ...

  3. php多进程编程相关资料(以备参考)

    进程与线程的区别 要了解二者的区别与联系,首先得对进程与线程有一个宏观上的了解. 进程,是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念,竟争计算机系统资源的基本单位.每一个进程都 ...

  4. RabbitMQ文档翻译——Hello World!(上)

    文章主要翻译自RabbitMQ官方文档,主要是为了练习英语翻译,顺便学习一下RabbitMQ

  5. 电子印章在Odoo的实现步骤

    1. 首先用PS制作一个电子印章,具体步骤可参考 http://www.jb51.net/photoshop/173568.html 2. 给Odoo中的pdf添加印章的原理,就是利用Odoo的QWe ...

  6. Spark 介绍(基于内存计算的大数据并行计算框架)

    Spark 介绍(基于内存计算的大数据并行计算框架)  Hadoop与Spark 行业广泛使用Hadoop来分析他们的数据集.原因是Hadoop框架基于一个简单的编程模型(MapReduce),它支持 ...

  7. Linux中cp直接覆盖不提示的方法

    新做了服务器,cp覆盖时,无论加什么参数-f之类的还是提示是否覆盖,这在大量cp覆盖操作的时候是不能忍受的. 把a目录下的文件复制到b目录 cp –r a/* b 执行上面的命令时,b存在的每个文件都 ...

  8. .net dll类库 生成chm说明文档

    效果图: 制作步骤: 1.下载Sandcastle http://shfb.codeplex.com/releases/view/105809 2.下载Html Help WorkShop http: ...

  9. hbase源码系列(六)HMaster启动过程

    这一章是server端开始的第一章,有兴趣的朋友先去看一下hbase的架构图,我专门从网上弄下来的. 按照HMaster的run方法的注释,我们可以了解到它的启动过程会去做以下的动作. * <l ...

  10. powerdesigner 导出excel

    PD菜单栏中,依次点击 Tools ->Excute Commands->Edit/Run Script.. 填入 '*********************************** ...