??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲香肠在线观看,不卡av在线播放,国产一区免费在线http://www.aygfsteel.com/stevenjohn/category/51969.html那些青春的岁?/description>zh-cnThu, 14 Jun 2012 01:16:25 GMTThu, 14 Jun 2012 01:16:25 GMT60深入研究ServletU程安全性问?/title><link>http://www.aygfsteel.com/stevenjohn/archive/2012/06/14/380730.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Thu, 14 Jun 2012 01:12:00 GMT</pubDate><guid>http://www.aygfsteel.com/stevenjohn/archive/2012/06/14/380730.html</guid><wfw:comment>http://www.aygfsteel.com/stevenjohn/comments/380730.html</wfw:comment><comments>http://www.aygfsteel.com/stevenjohn/archive/2012/06/14/380730.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/stevenjohn/comments/commentRss/380730.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/stevenjohn/services/trackbacks/380730.html</trackback:ping><description><![CDATA[<strong>?要:介绍了Servlet多线E机Ӟ通过一个实例ƈl合Java 的内存模型说明引起ServletU程不安全的原因Q给Z保证ServletU程安全的三U解x案,q说明三U方案在实际开发中的取舍?br /><br />  关键字:Servlet U程安全 同步 Java内存模型 实例变量<span> </span><br /><br />  Servlet/JSP技术和ASP、PHP{相比,׃其多U程q行而具有很高的执行效率。由于Servlet/JSP默认是以多线E模式执行的Q所以,在编写代码时需要非常细致地考虑多线E的安全性问题。然而,很多人编写Servlet/JSPE序时ƈ没有注意到多U程安全性的问题Q这往往造成~写的程序在量用户讉K时没有Q何问题,而在q发用户上升C定值时Q就会经常出C些莫明其妙的问题?br /><br />  Servlet的多U程机制</strong><br /><strong> <span> </span><br />  Servlet体系l构是徏立在Java多线E机制之上的Q它的生命周期是由Web容器负责的。当客户端第一ơ请求某个ServletӞServlet容器会Ҏweb.xml配置文g实例化这个ServletcR当有新的客Lh该ServletӞ一般不会再实例化该Servletc,也就是有多个U程在用这个实例。Servlet容器会自动用线E池{技术来支持pȝ的运行,如图1所C?br /><br /></strong> <table border="0" width="90%"> <tbody> <tr> <td><strong><img src="http://hiphotos.baidu.com/stevenjohn/pic/item/05b7b99c033b5bb5b839395436d3d539b700bc3c.jpg" alt="" /><br /></strong>? ServletU程?/td></tr></tbody></table><br />  q样Q当两个或多个线E同时访问同一个ServletӞ可能会发生多个线E同时访问同一资源的情况,数据可能会变得不一致。所以在用Servlet构徏的Web应用时如果不注意U程安全的问题,会所写的ServletE序有难以发现的错误?br /><br />  <strong>Servlet的线E安全问?br /></strong><br />  Servlet的线E安全问题主要是׃实例变量使用不当而引LQ这里以一个现实的例子来说明?br /><br /> <table border="1" width="90%"> <tbody> <tr> <td>Import javax.servlet. *;<span> </span><br />Import javax.servlet.http. *;<span> </span><br />Import java.io. *;<span> </span><br />Public class Concurrent Test extends HttpServlet {PrintWriter output;<span> </span><br />Public void service (HttpServletRequest request,<br />HttpServletResponse response) throws ServletException, IOException {String username;<br />Response.setContentType ("text/html; charset=gb2312");<br />Username = request.getParameter ("username");<span> </span><br />Output = response.getWriter ();<span> </span><br />Try {Thread. sleep (5000); //ZH出q发问题Q在q设|一个g?br />} Catch (Interrupted Exception e){}<br />output.println("用户?"+Username+"<BR>");<span> </span><br />}<br />}</td></tr></tbody></table><br />  该Servlet中定义了一个实例变量outputQ在serviceҎ其赋gؓ用户的输出。当一个用戯问该ServletӞE序会正常的q行Q但当多个用户ƈ发访问时Q就可能会出现其它用L信息昄在另外一些用L览器上的问题。这是一个严重的问题。ؓ了突出ƈ发问题,便于试、观察,我们在回昄户信息时执行了一个g时的操作。假讑ַ在web.xml配置文g中注册了该ServletQ现有两个用户a和b同时讉K该ServletQ可以启动两个IE览器,或者在两台机器上同时访问),卛_时在览器中输入Q?br /><br />  aQ?http://localhost: 8080/servlet/ConcurrentTest? Username=a<br /><br />  bQ?http://localhost: 8080/servlet/ConcurrentTest? Username=b<br /><br />  如果用户b比用户a回R的时间稍慢一点,得到如?所C的输出Q?br /><br /> <table border="0" width="90%"> <tbody> <tr> <td><img src="http://hiphotos.baidu.com/stevenjohn/pic/item/a790ee2062d0f703d97f8c7608fa513d2497c5d1.jpg" alt="" /><br />? a用户和b用户的浏览器输出</td></tr></tbody></table><br />  从图2中可以看刎ͼWeb服务器启动了两个U程分别处理来自用户a和用户b的请求,但是在用户a的浏览器上却得到一个空白的屏幕Q用户a的信息显C在用户b的浏览器上。该Servlet存在U程不安全问题。下面我们就从分析该实例的内存模型入?观察不同时刻实例变量output的值来分析使该ServletU程不安全的原因?br /><br />  Java的内存模型JMMQJava Memory ModelQJMM主要是ؓ了规定了U程和内存之间的一些关pR根据JMM的设计,pȝ存在一个主内存(Main Memory)QJava中所有实例变量都储存在主存中Q对于所有线E都是共享的。每条线E都有自q工作内存(Working Memory)Q工作内存由~存和堆栈两部分l成Q缓存中保存的是d中变量的拯Q缓存可能ƈ不dd同步Q也是~存中变量的修改可能没有立刻写到d中;堆栈中保存的是线E的局部变量,U程之间无法怺直接讉K堆栈中的变量。根据JMMQ我们可以将论文中所讨论的Servlet实例的内存模型抽象ؓ?所C的模型?br /><br /> <table border="0" width="90%"> <tbody> <tr> <td><img src="http://hiphotos.baidu.com/stevenjohn/pic/item/4ea4efd7f703918fe91c2460513d26975beec4d1.jpg" alt="" /><br />? Servlet实例的JMM模型</td></tr></tbody></table><br />  下面Ҏ?所C的内存模型Q来分析当用户a和b的线E(UCؓaU程、bU程Qƈ发执行时QServlet实例中所涉及变量的变化情况及U程的执行情况,如图4所C?br /><br /> <table border="1" cellspacing="0" cellpadding="2" width="85%"> <tbody> <tr> <td>调度时刻</td> <td>aU程</td> <td>bU程</td></tr> <tr> <td>T1</td> <td>讉KServlet面</td> <td> </td></tr> <tr> <td>T2</td> <td> </td> <td>讉KServlet面</td></tr> <tr> <td>T3</td> <td>output=a的输出username=a休眠5000毫秒Q让出CPU</td> <td> </td></tr> <tr> <td>T4</td> <td> </td> <td>output=b的输出(写回dQusername=b休眠5000毫秒Q让出CPU</td></tr> <tr> <td>T5</td> <td>在用户b的浏览器上输出aU程的username的?aU程l止?/td> <td> </td></tr> <tr> <td>T6</td> <td> </td> <td>在用户b的浏览器上输出bU程的username的?bU程l止?/td></tr></tbody></table>                  ? Servlet实例的线E调度情?br /><br />  从图4中可以清楚的看到Q由于bU程对实例变量output的修改覆盖了aU程对实例变量output的修改,从而导致了用户a的信息显C在了用户b的浏览器上。如果在aU程执行输出语句ӞbU程对output的修改还没有hC存,那么不会出现图2所C的输出l果Q因此这只是一U偶然现象,但这更增加了E序潜在的危险性?span> </span> <p><strong></strong> </p> <p><strong></strong> </p> <p><strong>设计U程安全的Servlet</strong><br /><br />  通过上面的分析,我们知道了实例变量不正确的用是造成ServletU程不安全的主要原因。下面针对该问题l出了三U解x案ƈҎ案的选取l出了一些参考性的?br /><br />  1、实?SingleThreadModel 接口<br /><br />  该接口指定了pȝ如何处理对同一个Servlet的调用。如果一个Servlet被这个接口指?那么在这个Servlet中的serviceҎ不会有两个U程被同时执行,当然也就不存在线E安全的问题。这U方法只要将前面的Concurrent Testcȝcd定义更改为:<br /><br /></p> <p> <table border="1" width="90%"> <tbody> <tr> <td>Public class Concurrent Test extends HttpServlet implements SingleThreadModel {<br />…………<br />}</td></tr></tbody></table></p> <p><br />  2、同步对׃n数据的操?br /><br />  使用synchronized 关键字能保证一ơ只有一个线E可以访问被保护的区D,在本论文中的Servlet可以通过同步块操作来保证U程的安全。同步后的代码如下:<span> </span><br /><br /></p> <p> <table border="1" width="90%"> <tbody> <tr> <td>…………<br />Public class Concurrent Test extends HttpServlet { …………<br />Username = request.getParameter ("username");<span> </span><br />Synchronized (this){<br />Output = response.getWriter ();<span> </span><br />Try {<br />Thread. Sleep (5000);<br />} Catch (Interrupted Exception e){}<br />output.println("用户?"+Username+"<BR>");<span> </span><br />}<span> </span><br />}<br />}</td></tr></tbody></table></p> <p><br />  3、避免用实例变?br /><br />  本实例中的线E安全问题是由实例变量造成的,只要在Servlet里面的Q何方法里面都不用实例变量,那么该Servlet是U程安全的?br /><br />  修正上面的Servlet代码Q将实例变量改ؓ局部变量实现同L功能Q代码如下:<br /><br /></p> <p> <table border="1" width="90%"> <tbody> <tr> <td>……<span> </span><br />Public class Concurrent Test extends HttpServlet {public void service (HttpServletRequest request, HttpServletResponse<span> </span><br />Response) throws ServletException, IOException {<br />Print Writer output;<span> </span><br />String username;<br />Response.setContentType ("text/html; charset=gb2312");<br />……<span> </span><br />}<span> </span><br />}</td></tr></tbody></table></p> <p><br />  对上面的三种Ҏq行试Q可以表明用它们都能设计出线E安全的ServletE序。但是,如果一个Servlet实现了SingleThreadModel接口QServlet引擎ؓ每个新的h创徏一个单独的Servlet实例Q这引起大量的pȝ开销。SingleThreadModel在Servlet2.4中已不再提倡用;同样如果在程序中使用同步来保护要使用的共享的数据Q也会ɾpȝ的性能大大下降。这是因同步的代码块在同一时刻只能有一个线E执行它Q得其同时处理客户h的吞吐量降低Q而且很多客户处于d状态。另外ؓ保证d内容和线E的工作内存中的数据的一致性,要频J地h~存,q也会大大地影响pȝ的性能。所以在实际的开发中也应避免或最化 Servlet 中的同步代码Q在Serlet中避免用实例变量是保证ServletU程安全的最佳选择。从Java 内存模型也可以知道,Ҏ中的临时变量是在栈上分配I间Q而且每个U程都有自己U有的栈I间Q所以它们不会媄响线E的安全?br /><br />  <strong>结</strong><br /><br />  Servlet的线E安全问题只有在大量的ƈ发访问时才会昄出来Qƈ且很隑֏玎ͼ因此在编写ServletE序时要特别注意。线E安全问题主要是由实例变量造成?因此在Servlet中应避免使用实例变量。如果应用程序设计无法避免用实例变量,那么使用同步来保护要使用的实例变量,但ؓ保证pȝ的最x能Q应该同步可用性最的代码路径?/p> <p> </p><img src ="http://www.aygfsteel.com/stevenjohn/aggbug/380730.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/stevenjohn/" target="_blank">abin</a> 2012-06-14 09:12 <a href="http://www.aygfsteel.com/stevenjohn/archive/2012/06/14/380730.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <a href="http://www.aygfsteel.com/" title="狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频">狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频</a> </div> </footer> վ֩ģ壺 <a href="http://" target="_blank">ʯ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">¤</a>| <a href="http://" target="_blank">¤</a>| <a href="http://" target="_blank">ʤ</a>| <a href="http://" target="_blank">˳</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ϻӿ</a>| <a href="http://" target="_blank">¡</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ĺ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ƺ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">֦</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ͼƬ</a>| <a href="http://" target="_blank">̳</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">˫</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ƽ</a>| <a href="http://" target="_blank">կ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">㽭ʡ</a>| <a href="http://" target="_blank">ͨ</a>| <a href="http://" target="_blank">踽</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ֶ</a>| <a href="http://" target="_blank">ƽ</a>| <a href="http://" target="_blank">ȫ</a>| <a href="http://" target="_blank">Ϫ</a>| <a href="http://" target="_blank"></a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>