📄 轻松使用线程:同步不是敌人.htm
字号:
<P>还有一点值得注意的是,简单地同步存取器方法(或声明下层的字段为
<CODE>volatile</CODE>)可能并不足以保护一个共享字段。可以考虑下面的示例:</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1><TBODY>
<TR>
<TD><PRE><CODE> ...
private int foo;
public synchronized int getFoo() { return foo; }
public synchronized void setFoo(int f) { foo = f; }
</CODE>
</PRE></TD></TR></TBODY></TABLE><BR><BR>
<P>如果一个调用者想要增加 <CODE>foo</CODE> 属性值,以下完成该功能的代码就不是线程安全的:</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1><TBODY>
<TR>
<TD><PRE><CODE> ...
setFoo(getFoo() + 1);
</CODE>
</PRE></TD></TR></TBODY></TABLE><BR><BR>
<P>如果两个线程试图同时增加 <CODE>foo</CODE> 属性值,结果可能是 <CODE>foo</CODE> 的值增加了 1 或
2,这由计时决定。调用者将需要同步一个锁,才能防止这种争用情况;一个好方法是在 JavaDoc
类中指定同步哪个锁,这样类的调用者就不需要自己猜了。</P>
<P>以上情况是一个很好的示例,说明我们应该注意多层次粒度的数据完整性;同步存取器方法确保调用者能够存取到一致的和最近版本的属性值,但如果希望属性的将来值与当前值一致,或多个属性间相互一致,我们就必须同步复合操作
— 可能是在一个粗粒度的锁上。</P>
<P><A id=6 name=6></A><SPAN
class=atitle2>如果情况不确定,考虑使用同步包装</SPAN><BR>有时,在写一个类的时候,我们并不知道它是否要用在一个共享环境里。我们希望我们的类是线程安全的,但我们又不希望给一个总是在单线程环境内使用的类加上同步的负担,而且我们可能也不知道使用这个类时合适的锁粒度是多大。幸运的是,通过提供同步包装,我们可以同时达到以上两个目的。Collections
类就是这种技术的一个很好的示例;它们是非同步的,但在框架中定义的每个接口都有一个同步包装(例如,<CODE>
Collections.synchronizedMap()</CODE>),它用一个同步的版本来包装每个方法。</P>
<P><A id=7 name=7></A><SPAN class=atitle2>结论</SPAN><BR>虽然 JLS
给了我们可以使我们的程序线程安全的工具,但线程安全也不是天上掉下来的馅饼。使用同步会蒙受性能损失,而同步使用不当又会使我们承担数据混乱、结果不一致或死锁的风险。幸运的是,在过去的几年内
JVM
有了很大的改进,大大减少了与正确使用同步相关的性能损失。通过仔细分析在线程间如何共享数据,适当地同步对共享数据的操作,可以使得您的程序既是线程安全的,又不会承受过多的性能负担。</P><!-- RESOURCES -->
<P><A id=resources name=resources><SPAN class=atitle2>参考资料</SPAN></A></P>
<UL>
<LI>请点击文章顶部或底部的<B>讨论</B>进入由 Brian Goetz 主持的,关于“Java 线程:技巧、窍门和技术”的<A
href="http://www-105.ibm.com/developerWorks/java_df.nsf/AllViewTemplate?OpenForm&RestrictToCategory=23">
讨论论坛</A>。<BR><BR>
<LI>Jack Shirazi 编写的 <A
href="http://www.amazon.com/exec/obidos/ASIN/0596000154/none0b69"><I>Java
Performance Tuning</I></A>(O'Reilly & Associates, 2000)可以为在 Java
平台上解决性能问题提供指导。本书引用的与本书一起提供的参考资料提供了很好的<A
href="http://www.javaperformancetuning.com/tips.shtml">性能调试技巧</A>。<BR><BR>
<LI>Dov Bulka 的 <A
href="http://www.amazon.com/exec/obidos/ASIN/0201704293/none0b69"><I>Java
Performance and Scalability,第 1 卷:Server-Side Programming
Techniques</I></A>(Addison-Wesley,2000)提供了大量的设计技巧和诀窍,可帮助您增强自己的应用程序的性能。<BR><BR>
<LI>Steve Wilson 和 Jeff Kesselman 的 <A
href="http://www.amazon.com/exec/obidos/ASIN/0201709694/none0b69"><I>Java
Platform Performance: Strategies and
Tactics</I></A>(Addison-Wesley,2000)为有经验的 Java 程序员提供了生成快速、有效的 Java
代码的技术。<BR><BR>
<LI>Brian Goetz 最近的著作“<A
href="http://www.javaworld.com/jw-02-2001/jw-0209-double.html">Double-checked
locking: Clever, but broken</A>”(JavaWorld,2001 年 2 月)详细探索了 JMM
并描述了特定情况下不使用同步的惊人后果。<BR><BR>
<LI>公认的多线程权威 Allen Holub 在他的文章“<A
href="http://www.javaworld.com/jw-02-2001/jw-0209-toolbox.html">警告:多处理器世界中的线程</A>”(JavaWorld,2001
年 2 月)中揭示了为什么用于减少同步负担的大多数技巧都不起作用。<BR><BR>
<LI>Peter Haggar 描述了怎样<A
href="http://www-900.ibm.com/developerWorks/cn/java/praxis/pr52.shtml">用固定的,循环的顺序获取多个锁定以避免死锁</A>(developerWorks,2000
年 9 月)。<BR><BR>
<LI>在他的文章“<A
href="http://www-900.ibm.com/developerWorks/cn/java/j-thread/index.shtml">编写多线程
Java 应用</A>”(developerWorks,2001 年 9 月)中,Alex Roetter 介绍了 Java Thread
API,概括了多线程涉及的问题,并为一般性的问题提供了解决方案。<BR><BR>
<LI>Doug Lea 的 <A
href="http://www.amazon.com/exec/obidos/ASIN/0201310090/none0b69"><I>Concurrent
Programming in Java,第 2 版</I></A>(Addison-Wesley,1999)是关于 Java
语言中多线程编程的敏感问题的权威书籍。<BR><BR>
<LI>“<A href="http://gee.cs.oswego.edu/dl/cpj/jmm.html">同步和 Java
内存模型</A>”摘录自 Doug Lea 的关于 <CODE>synchronized</CODE> 的实际意义的著作。<BR><BR>
<LI>Bill Pugh 的 <A
href="http://www.cs.umd.edu/~pugh/java/memoryModel">Java 内存模型</A>为您学习
JMM 提供了一个很好的起点。<BR><BR>
<LI><A
href="http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html">“Double
Checked Locking is Broken”</A>声明描述了为什么 DCL 在用 Java 语言实现时没有用。<BR><BR>
<LI>Bill Joy、Guy Steele 和 James Gosling 的 <A
href="http://www.amazon.com/exec/obidos/ASIN/0201310082/none0b69"><I>The
Java Language Specification,第 2 版</I></A>(Addison-Wesley,2000)的第 17 章描述了
Java 内存模型的深层细节问题。<BR><BR>
<LI>IBM 的这篇文章描述了如何<A
href="http://www-900.ibm.com/developerWorks/cn/cgi-bin/click.cgi?url=www7.software.ibm.com/vad.nsf/Data/Document2351?OpenDocument&p=1&BCT=3&Footer=1&origin=j">
优化 WebSphere 中的加锁</A>使不同的事务处理并发地读取同一个状态且仅在更新的时候检查数据完整性。<BR><BR>
<LI>IBM T.J. Watson 研究中心有一整个项目组投入到<A
href="http://www-900.ibm.com/developerWorks/cn/cgi-bin/click.cgi?url=www.research.ibm.com/PM/perf_mgt.html&origin=j">
性能管理</A>中。<BR><BR>
<LI>请在 <A
href="http://www-900.ibm.com/developerWorks/cn/java/">developerWorks
Java 技术专区</A>查找更多的参考资料。 </LI></UL><BR><BR><!-- AUTHOR BIOS --><!-- Make author heading singular or plural as needed -->
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><A id=author1 name=author1><SPAN class=atitle2>关于作者</SPAN></A>
<BR>Brian Goetz 是一名软件顾问,并且过去 15 年来一直是专业的软件开发人员。他是 <A
href="http://www.quiotix.com/">Quiotix</A>,一家坐落在 Los
Altos,California 的软件开发和咨询公司的首席顾问。请通过 <A
href="mailto:brian@quiotix.com">brian@quiotix.com</A> 与 Brian
联系。</TD></TR></TBODY></TABLE></TD>
<TD width=10><IMG height=1 alt="" src="轻松使用线程:同步不是敌人.files/c.gif" width=10
border=0></TD></TR></TBODY></TABLE><!-- END PAPER BODY --><BR clear=all><IMG
height=10 alt="" src="轻松使用线程:同步不是敌人.files/c.gif" width=100 border=0><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD align=right width="100%"><A
href="http://www-900.ibm.com/developerWorks/cn/java/j-threads/index.shtml#top">到页首</A></TD>
<TD width=5><IMG height=1 alt="" src="轻松使用线程:同步不是敌人.files/c.gif" width=5
border=0></TD></TR>
<TR vAlign=top>
<TD bgColor=#000000 colSpan=2><IMG height=1 alt=""
src="轻松使用线程:同步不是敌人.files/c.gif" width=100 border=0></TD></TR>
<TR vAlign=top>
<TD bgColor=#ffffff colSpan=2><IMG height=8 alt=""
src="轻松使用线程:同步不是敌人.files/c.gif" width=100 border=0></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=10 width="100%" border=0>
<TBODY>
<TR vAlign=top>
<TD>
<FORM action=/developerWorks/cn/cnratings.nsf/RateArticle?CreateDocument
method=post><INPUT type=hidden
value="Threading Lightly: Synchronization is not the enemy"
name=ArticleTitle> <INPUT type=hidden value=Java name=Zone> <INPUT
type=hidden value=/developerWorks/cn/thankyou/feedback-java.html
name=RedirectURL> <A id=rating name=rating><B>您对这篇文章的看法如何?</B></A>
<TABLE cellSpacing=0 cellPadding=0 width=600 border=0>
<TBODY>
<TR>
<TD colSpan=5><IMG height=8 alt="" src="轻松使用线程:同步不是敌人.files/c.gif"
width=100 border=0></TD></TR>
<TR vAlign=top>
<TD width="16%"><INPUT type=radio value=5 name=Rating>真棒!(5)</TD>
<TD width="20%"><INPUT type=radio value=4 name=Rating>好材料 (4)</TD>
<TD width="24%"><INPUT type=radio value=3 name=Rating>一般;尚可 (3)</TD>
<TD width="22%"><INPUT type=radio value=2 name=Rating>需提高 (2)</TD>
<TD width="18%"><INPUT type=radio value=1 name=Rating>太差!
(1)</TD></TR></TBODY></TABLE><BR><B>建议?</B><BR><TEXTAREA name=Comments rows=5 wrap=virtual cols=60></TEXTAREA><BR><BR><INPUT type=submit value=提交反馈意见></FORM></TD></TR>
<TR vAlign=top>
<TD bgColor=#ffffff><IMG height=8 alt="" src="轻松使用线程:同步不是敌人.files/c.gif"
width=100 border=0></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD align=right>(c) Copyright IBM Corp. 2001, (c) Copyright IBM China
2001, All Right Reserved</TD></TR>
<TR vAlign=top>
<TD class=bbg height=21> <A class=mainlink
href="http://www-900.ibm.com/developerWorks/cn/cgi-bin/click.cgi?url=www-900.ibm.com/cn/ibm/index.shtml&origin=dwhead">关于
IBM</A><SPAN class=divider> | </SPAN><A
class=mainlink
href="http://www-900.ibm.com/developerWorks/cn/cgi-bin/click.cgi?url=www-900.ibm.com/cn/ibm/privacy/index.shtml&origin=dwhead">隐私条约</A><SPAN
class=divider> | </SPAN><A class=mainlink
href="http://www-900.ibm.com/developerWorks/cn/cgi-bin/click.cgi?url=www-900.ibm.com/cn/ibm/legal/index.shtml&origin=dwhead">使用条款</A><SPAN
class=divider> | </SPAN><A class=mainlink
href="http://www-900.ibm.com/developerWorks/cn/cgi-bin/click.cgi?url=www-900.ibm.com/cn/ibm/contact/index.shtml&origin=dwhead">联系
IBM</A></TD></TR></TBODY></TABLE>
<SCRIPT language=JavaScript1.2 src="轻松使用线程:同步不是敌人.files/stats.js"
type=text/javascript></SCRIPT>
<NOSCRIPT><IMG height=1 alt=""
src="D:\专业\JAVA\J2SE\轻松使用线程:同步不是敌人.files\c(1).gif" width=1 border=0></NOSCRIPT>
</A></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -