- 浏览: 550142 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
hdblocal_:
为什么messageReceived之后,再encode,有点 ...
MINA框架使用总结 -
andey007518:
MINA框架使用总结 -
ymm8505:
我自己的理解 CopyOnWriteArrayList 这个 ...
ArrayList遍历的同时删除 -
spring_springmvc:
可以参考最新的文档:如何在eclipse jee中检出项目并转 ...
Eclipse快捷键-方便查找 -
netwelfare:
文章讲解的不够详细,ArrayList在遍历的同时如果去删除或 ...
ArrayList遍历的同时删除
这个问题网上一直没有搜到很详细的解释,也可能是高人的解释不符合我的理解方式。所以自己到网上搜集了写资料再加自己的想法,随便写了点东西发到论坛上,希望大家给予修正意见,看我是否理解对了。
一般servlet在jvm中只有个对象,当多个请求来请求一个jsp页面的时候,实际上都是调用这个jsp编译好的servlet类doPost或者doGet方法。
现在我就模拟一个servlet的调用过程
new Runnalbe{ public run(){ Request requset = new Request(); Resposne response = new Response(); //servlet对象只有一个,是容器自动生成的,这里模拟一个servlet的调用过程。 servlet.doPost (request,response); } }
当有多个请求过来的时候,相当于多个线程来执行这段代码。上面那个servlet的实现类HelloServlet:
public class HelloServlet extends HttpServlet { private int j =0; public void doPost(HttpServletRequest request, HttpServletResponse response){ int i=0; i++; j++; //这里的i和j那个是线程安全的那个不是呢,后面我们将从线程的堆栈,和jvm的堆的概念来解释这个问题 //request 和 response 对象是不是线程安全的 } }
JVM是基于堆栈的虚拟机.JVM为每个新创建的线程都分配一个堆栈(这里的堆栈不是指堆).也就是说,对于一个Java程序来说,它的运行
就是通过对堆栈的操作来完成的。堆栈以帧为单位保存线程的状态。JVM对堆栈只进行两种操作:以帧为单位的压栈和出栈操作。
我们知道,某个线程正在执行的方法称为此线程的当前方法.我们可能不知道,当前方法使用的帧称为当前帧。当线程激活一个
Java方法,JVM就会在线程的Java堆栈里新压入一个帧。这个帧自然成为了当前帧.在此方法执行期间,这个帧将用来保存参数,局部变量,中间计算过程和其他数据.这个帧在这里和编译原理中的活动纪录的概念是差不多的。
这里还要补充一下堆的概念:
堆(heap)是放实例和数组的,JAVA里面没有全局变量这个概念,所有变量都是以类的属性或者参数等形式存在的。GC是自动回收.但是数组和类的引用是放在堆栈中。
学过汇编的可能都知道,数据是是存储在栈内的,执行的代码逻辑是可以共用的。当多个线程来访问同一个方法的时候,共享同一段代码逻辑,但是方法对应的数据是存储在各自的堆栈(stack)中,如局部变量和参数还有对象的引用(局部变量和参数也可能是对象的引用)。所以多线程并发的情况下,出现不同步的现象主要是因为各自堆栈存放的某些数据是共享的,说白了就是同一个数据的引用(不是copy)被存放在不同的堆栈中。
例如类X的对象A被多个线程访问,他的引用被保存在多个线程的堆栈中,当多个线程访问A对象的某个属性b的时候如果不加锁就会出现不同步的现象。所以为了避免这种情况发生一是加锁,二就是为每个线程都生成一个类X的对象,这样每个线程的堆栈中存放的类X引用所对应的堆中的对象都不一样,当然就不存在共享的问题。
现在我们回到开始那个例子,可以很好的分析出参数request,respone,i是线程安全的,而j是线程不安全的;
为什么?request,respone是线程安全的是因为每个线程对应的request,respone对象都是不一样的,不存在共享问题。i是线程安全的是应为i是局部变量,每个线程的堆栈中存放的值也是各自独立的。
j线程不安全是应为它是类HelloServlet的属性,找了很多资料都不能说清楚它到底放在那里,从实际效果来看,它是不安全的,所以应该是放在和类对象一起放在堆里面的,堆里面估计是复制了一份过来,因为HelloServlet对多个线程而言只有
一个实例,所以存在共享问题。
评论
servlet是单实例多线程运行方式,所以对象变量线程不安全,局部变量线程安全
同意! local variable不存在race condition, 但是instance variable存在race condition.
请诸位看这里,
http://book.javanb.com/java-concurrency-in-Practice/ch02lev1sec2.html
The definition of race condition,
The possibility of incorrect results in the presence of unlucky timing is so important in concurrent programming that it has a name: a race condition.
servlet是单例的还是很有道理的!
所以基础数据声明后,不管怎么赋值,都不会有线程问题(int i=1;int j=i)两个int 类型的数据根本就是2个数据体。
局部变量本来就是在某个线程的生命周期内声明的变量,如果不用特别的方法保存它,其他线程根本没办法引用到它,所以也就没有线程同步的问题存在
而引用同一个对象,修改得是同一个堆中的数据,线程同步腐蚀就出现了,如果没有状态数据,被使用对象也就没有被线程修改得可能,也就没有线程安全问题
说的不错,很认同,如《 进行运算而产生的中间结果会放在cpu的寄存器中》 这句话,比如说j=5;j在第一个线程自增后的结果6保存在CPU的临时寄存器中,假如寄存器自增的值6没有及时回写到内存中去,而同时又有另一个线程执行了此代码,则刚才有第一个线程自增的结果将被第二个线程清洗掉,然后后一个线程在j原先的基础上5上自增1为6,回写到内存。退出代码,假如此时第一个线程被唤醒,再次见寄存器中的值写入到内存中,还是6。经过了两次自增并应该是7,但内存中的值是6,就导致了线程不同步,主要是由于自增运算造成的,而基础数据的任何的赋值操作是不会导致线程安全问题。
如果一个对象下一刻的值 需要依赖原来的值,
就会在多线程下有同步的问题
所以基础数据声明后,不管怎么赋值,都不会有线程问题(int i=1;int j=i)两个int 类型的数据根本就是2个数据体。
局部变量本来就是在某个线程的生命周期内声明的变量,如果不用特别的方法保存它,其他线程根本没办法引用到它,所以也就没有线程同步的问题存在
而引用同一个对象,修改得是同一个堆中的数据,线程同步腐蚀就出现了,如果没有状态数据,被使用对象也就没有被线程修改得可能,也就没有线程安全问题
说的不错,很认同,如《 进行运算而产生的中间结果会放在cpu的寄存器中》 这句话,比如说j=5;j在第一个线程自增后的结果6保存在CPU的临时寄存器中,假如寄存器自增的值6没有及时回写到内存中去,而同时又有另一个线程执行了此代码,则刚才有第一个线程自增的结果将被第二个线程清洗掉,然后后一个线程在j原先的基础上5上自增1为6,回写到内存。退出代码,假如此时第一个线程被唤醒,再次见寄存器中的值写入到内存中,还是6。经过了两次自增并应该是7,但内存中的值是6,就导致了线程不同步,主要是由于自增运算造成的,而基础数据的任何的赋值操作是不会导致线程安全问题。
servlet是否线程安全取决容器的实现, 一般来说, servlet不是线程安全的, 你自要实现一个也无所谓。
共享会不会造成线程安全也是不对的.
确切的说, 如果一个对象的实例, 在多线程环境下, 如果API CALL会有状态的, 那么他一般就不是线程安全的。
简单明了,同意
servlet是否线程安全取决容器的实现, 一般来说, servlet不是线程安全的, 你自要实现一个也无所谓。
共享会不会造成线程安全也是不对的.
确切的说, 如果一个对象的实例, 在多线程环境下, 如果API CALL会有状态的, 那么他一般就不是线程安全的。
简单明了,同意
我先前刚好以为的和你说的相反,我以为容器为每个请求都创建一个新的servlet实例,这种情况下是线程安全的,如果实现singleModel什么的接口,系统将只创建一个servlet实例,分配给所有线程,这样就不安全了,看这个名字singleXX就不像是什么安全的东西,在servlet2.0版本中就不建议使用了,不过是为了节省内存开销。。
现在看大家都这么说,我估计是不是我的想法错了。。
servlet是单实例多线程运行方式,所以对象变量线程不安全,局部变量线程安全
说的很对,受教了。
没错,同一个servlet对于不同用户的请求使用不同的线程处理
servlet是否线程安全取决容器的实现, 一般来说, servlet不是线程安全的, 你自要实现一个也无所谓。
共享会不会造成线程安全也是不对的.
确切的说, 如果一个对象的实例, 在多线程环境下, 如果API CALL会有状态的, 那么他一般就不是线程安全的。
准确点说是堆数据共享
2)例如类X的对象A被多个线程访问,他的引用被保存在多个线程的堆栈中,
一个java虚拟机中只有一个堆被多个线程共享
我也没有验证过
而servlet是否是单例取决于容器的实现
一般来说不是单例的
不对吧,一般来说Servlet都是单例的。
public class TestServletSingle extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } response.getOutputStream().println(this.hashCode()); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
你在5秒内打开N个浏览器窗口试试,返回的都是相同的Hashcode。只有在context reload以后,Hashcode才发生变化。因为原来的servlet object销毁了,容器又新建了一个。
然而,Servlet的单例不由class来决定,而是由您在web.xml里配置的servlet-name来决定。也就是说每一个servlet-name只有1个单例。当你有3个不同的serlvet-name指定了相同的1个servlet-class时,容器会产生3个不同的servlet object。只有3个。
其实就是一个线程安全的问题
和servlet没有关系
你这个j是否线程安全取决于你的servlet是否是同一个对象
而servlet是否是单例取决于容器的实现
一般来说不是单例的
发表评论
-
为何在使用CMS gc算法时会出现连续两次full gc
2011-09-01 11:04 4920现象: jstat -gcutil pid 1000观察到 ... -
配置filter拦截forward之类的内部转发
2011-02-18 17:19 5959在servlet-2.3中,Filter会过滤一切请求,包括服 ... -
request.getRequestURI 与request.getServletPath() 区别
2011-02-16 19:38 7815路径:resin/webapps/my_proj/test/r ... -
ConcurrentHashMap中的remove方法的bug
2010-04-30 11:48 5775最近研究了一下 ConcurrentHashMap中源码发现j ... -
搭建Android开发环境
2010-04-05 23:22 1512在eclipse上安装Android 1.安装eclipse ... -
IoServer源代码阅读笔记
2009-08-23 21:57 2114NIO:写事件要尽量早的被注销. 1,IOServer用一 ... -
一个webapp目录下部署多个web应用
2009-08-21 10:34 2122在同一个resin下的webapp目录部署多个web应用,发现 ... -
java 的深度克隆
2009-07-01 20:07 1743只有实现了cloneable接口才算是真正的深度克隆. 在复 ... -
try finally return
2009-03-20 19:21 1212class Entry { ... -
String和==号的问题
2009-03-09 19:45 1198String name = "you" ... -
Bit数组
2009-01-20 18:56 2856public class BitArray{//用byte数组 ... -
关于Java占用内存的研究 (转载请注明作者zms)
2009-01-20 15:28 2935版权声明:转载时请以 ... -
几种通讯协议的比较
2009-01-20 15:26 5318一、综述 本文比较了RMI ... -
java基础知识总结
2009-01-06 00:50 2808http://wiki.caucho.com/Hessian_ ... -
Java基础-关于session的详细解释
2008-12-01 23:49 1312一、术语session 在我的经验里,session这个词 ... -
关于大量缓存对象回收的思考
2008-12-01 15:34 2635前几天面试,被问到了一个问题,如果当前有数亿条记录,但是缓存最 ... -
java 快速排序demo
2008-11-29 19:52 2017快速排序算法思想如下,先选取一个元素作为基准,然后根据这个基准 ... -
java 实现简单的文件拷贝
2008-11-26 17:36 6238昨天面试,面试官要我在黑板上写个java文件复制的代码,但是一 ... -
HashMap的遍历效率讨论
2008-11-26 11:31 3659经常遇到对HashMap中的key和value值对的遍历操作 ... -
Java ArrayList 实现
2008-11-25 23:02 3720ArrayList是List接口的一个可变长数组实现。实现了 ...
相关推荐
servlet线程安全问题servlet线程安全问题
Servlet是线程不安全的。Servlet体系是建立在java多线程的基础之上的,它的生命周期是由Tomcat 来维护的。当客户端第一次请求Servlet的时候,tomcat会根据web.xml配置文件实例化servlet, 当又有一个客户端访问该...
深入研究Servlet线程安全性问题...
servlet与Struts action线程安全问题分析
比较深刻地论述了Servlet线程安全性问题
servlet与Struts action线程安全问题分析 <br>===================================================== Servlet的线程安全问题只有在大量的并发访问时才会显现出来,并且很难发现,因此在编写Servlet程序时要...
当两个或多个线程同时访问同一个Servlet时,可能会发生多个线程同时访问同一资源的情况,数据可能会变得不一致,所以就很容易造成一系列的一些安全性问题。
先从Servlet的工作原理说起:首先简单解释一下Servlet接收和响应客户请求的过程,首先客户发送一个请求,Servlet是调用service()方法对请求
主要是关于Servlet模拟网上售票问题,引发的线程安全问题的思考,感兴趣的小伙伴们可以参考一下
{8.1}线程的常用属性与方法}{121}{section.8.1} {8.2}后台线程}{123}{section.8.2} {8.3}创建线程的两种方法}{123}{section.8.3} {8.4}Runnable}{123}{section.8.4} {8.5}Sleep阻塞与打断唤醒}{124}{section....
6.如何处理Servlet的线程不安全问题 1.最简单的就是不使用字段变量, 2.使用final修饰变量, 3.线程安全就是多线程操作同一个对象不会有问题,线程同步一般来保护线程安全, 所以可以在Servlet的线程里面加上同步...
Java web中servlet学习笔记 核心。servlet执行过程、servlet生命周期、继承类、创建servlet、servlet线程安全、配置信息
想简单模拟下servlet,看下什么是线程安全,现在发现自己写的程序问题了,果然线程不安全。
1、Servlet基本概念 2、Servlet基本运用、配置 3、Servlet生命周期 4、Servlet线程安全 5、Model2与MVC设计模式 6、过滤器 7、分页 8、上传组件SmartUpload 9、监听器 10、配置Tomcat连接池 11、实用技术
在多线程的环境下,Servlet必须能处理许多同时发生的请求。例外的情况是这个Servlet执行了SingleThreadModel接口,如果是那样的话,Servlet只能同时处理一个请求。 Servlet依照Servlet引擎的映射来响应客户端的请求...