锁定老帖子 主题:Servlet的线程安全问题
精华帖 (2) :: 良好帖 (0) :: 新手帖 (7) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-01-01
一个servlet的非线性安全说的这么复杂。哥们, 更简单的理解问题哦。
servlet是否线程安全取决容器的实现, 一般来说, servlet不是线程安全的, 你自要实现一个也无所谓。 共享会不会造成线程安全也是不对的. 确切的说, 如果一个对象的实例, 在多线程环境下, 如果API CALL会有状态的, 那么他一般就不是线程安全的。 |
|
返回顶楼 | |
发表时间:2009-01-03
最后修改:2009-01-03
我汗,不知道楼主到底像指导什么,servlet 本来就不是线程安全的,要安全实现一个好像叫做siglelon 啥的接口就线程安全了,不过性能也下降了,自己衡量,请参看sun的jee 文档,有例子说的非常清楚
|
|
返回顶楼 | |
发表时间:2009-01-03
"servlet 本来就不是线程安全的"
没错,同一个servlet对于不同用户的请求使用不同的线程处理 |
|
返回顶楼 | |
发表时间:2009-01-05
kaneg 写道 其实说简单一点就是:
servlet是单实例多线程运行方式,所以对象变量线程不安全,局部变量线程安全 说的很对,受教了。 |
|
返回顶楼 | |
发表时间:2009-01-20
servlet 是单实例的,多个线程可能会同时运行,当然这个实例是放在堆里面,由于堆是给多个线程共享的,每个线程的栈,都会referce这个实例,如果这个实例有实例变量,那不好意思,我们都可以访问,所以会早晨不安全的情况,请参看深入java虚拟机第二版 57页
|
|
返回顶楼 | |
发表时间:2009-01-21
kjj 写道 我汗,不知道楼主到底像指导什么,servlet 本来就不是线程安全的,要安全实现一个好像叫做siglelon 啥的接口就线程安全了,不过性能也下降了,自己衡量,请参看sun的jee 文档,有例子说的非常清楚
我先前刚好以为的和你说的相反,我以为容器为每个请求都创建一个新的servlet实例,这种情况下是线程安全的,如果实现singleModel什么的接口,系统将只创建一个servlet实例,分配给所有线程,这样就不安全了,看这个名字singleXX就不像是什么安全的东西,在servlet2.0版本中就不建议使用了,不过是为了节省内存开销。。 现在看大家都这么说,我估计是不是我的想法错了。。 |
|
返回顶楼 | |
发表时间:2009-01-21
sdh5724 写道 一个servlet的非线性安全说的这么复杂。哥们, 更简单的理解问题哦。
servlet是否线程安全取决容器的实现, 一般来说, servlet不是线程安全的, 你自要实现一个也无所谓。 共享会不会造成线程安全也是不对的. 确切的说, 如果一个对象的实例, 在多线程环境下, 如果API CALL会有状态的, 那么他一般就不是线程安全的。 简单明了,同意 |
|
返回顶楼 | |
发表时间:2009-03-06
Element&lina 写道 sdh5724 写道 一个servlet的非线性安全说的这么复杂。哥们, 更简单的理解问题哦。
servlet是否线程安全取决容器的实现, 一般来说, servlet不是线程安全的, 你自要实现一个也无所谓。 共享会不会造成线程安全也是不对的. 确切的说, 如果一个对象的实例, 在多线程环境下, 如果API CALL会有状态的, 那么他一般就不是线程安全的。 简单明了,同意 |
|
返回顶楼 | |
发表时间:2009-03-09
moshalanye 写道 一般我们新建对象,jvm 才会为我们新建存放对象的堆空间,里面有属于对象的方法体和属性,而对对象的引用和基础数据类型是存放在栈中的,而cpu运作时,进行运算而产生的中间结果会放在cpu的寄存器中。
所以基础数据声明后,不管怎么赋值,都不会有线程问题(int i=1;int j=i)两个int 类型的数据根本就是2个数据体。 局部变量本来就是在某个线程的生命周期内声明的变量,如果不用特别的方法保存它,其他线程根本没办法引用到它,所以也就没有线程同步的问题存在 而引用同一个对象,修改得是同一个堆中的数据,线程同步腐蚀就出现了,如果没有状态数据,被使用对象也就没有被线程修改得可能,也就没有线程安全问题 说的不错,很认同,如《 进行运算而产生的中间结果会放在cpu的寄存器中》 这句话,比如说j=5;j在第一个线程自增后的结果6保存在CPU的临时寄存器中,假如寄存器自增的值6没有及时回写到内存中去,而同时又有另一个线程执行了此代码,则刚才有第一个线程自增的结果将被第二个线程清洗掉,然后后一个线程在j原先的基础上5上自增1为6,回写到内存。退出代码,假如此时第一个线程被唤醒,再次见寄存器中的值写入到内存中,还是6。经过了两次自增并应该是7,但内存中的值是6,就导致了线程不同步,主要是由于自增运算造成的,而基础数据的任何的赋值操作是不会导致线程安全问题。 |
|
返回顶楼 | |
发表时间:2009-03-09
wujie2008 写道 moshalanye 写道 一般我们新建对象,jvm 才会为我们新建存放对象的堆空间,里面有属于对象的方法体和属性,而对对象的引用和基础数据类型是存放在栈中的,而cpu运作时,进行运算而产生的中间结果会放在cpu的寄存器中。
所以基础数据声明后,不管怎么赋值,都不会有线程问题(int i=1;int j=i)两个int 类型的数据根本就是2个数据体。 局部变量本来就是在某个线程的生命周期内声明的变量,如果不用特别的方法保存它,其他线程根本没办法引用到它,所以也就没有线程同步的问题存在 而引用同一个对象,修改得是同一个堆中的数据,线程同步腐蚀就出现了,如果没有状态数据,被使用对象也就没有被线程修改得可能,也就没有线程安全问题 说的不错,很认同,如《 进行运算而产生的中间结果会放在cpu的寄存器中》 这句话,比如说j=5;j在第一个线程自增后的结果6保存在CPU的临时寄存器中,假如寄存器自增的值6没有及时回写到内存中去,而同时又有另一个线程执行了此代码,则刚才有第一个线程自增的结果将被第二个线程清洗掉,然后后一个线程在j原先的基础上5上自增1为6,回写到内存。退出代码,假如此时第一个线程被唤醒,再次见寄存器中的值写入到内存中,还是6。经过了两次自增并应该是7,但内存中的值是6,就导致了线程不同步,主要是由于自增运算造成的,而基础数据的任何的赋值操作是不会导致线程安全问题。 如果一个对象下一刻的值 需要依赖原来的值, 就会在多线程下有同步的问题 |
|
返回顶楼 | |