在什么情况下,您不必同步将数据从一个线程传播到另一个线程?
答案 0 :(得分:4)
试试Java Synchronization tutorial。它将引导您完成基础知识。还要意识到通过同步手动控制线程很慢并且极易出错。其他成语(和语言)已经发展,使开发人员免于管理原始线程的复杂性。
答案 1 :(得分:3)
在某些情况下,您不必同步将数据从一个线程传播到另一个线程,因为JVM 隐式为您执行同步。
这些案例包括:
答案 2 :(得分:3)
如果您的应用程序只有一个线程(不计入垃圾收集线程,这是VM的职责),则不需要使用同步。一些库,如Swing,引入了多线程,所以你必须要注意。
答案 3 :(得分:3)
我的问题是:“为什么不将所有方法标记为同步”或“为什么并非所有方法都自动同步”
如果所有内容都已同步,您可能无法从多线程中获益。多个线程可以处于活动状态,但一次只能有一个线程可以通过您的代码。
此外,同步会产生开销,这可能很大,因为JVM会检查互斥锁。
答案 4 :(得分:1)
如果您可以坚持一个线程,则无需同步。如果你需要另一个线程,那么同步所有与该线程相关的线程是一种避免问题的简单方法。
但是,如果您有多个线程并想要充分利用它们,您希望尽一切可能避免同步。在这种情况下,您需要同步的唯一时间是当您有一组必须彼此一致的字段以及可能从另一个线程访问其中一个或多个字段时。然后,只有这样,你需要一个同步块。
请注意,非线程安全类的任何对象都包含一整套此类字段,即使单独使用也必须同步:
private final Collection bigList;
synchronized (bigList) { // Protect bigList!
bigList.add( something );
}
也只有一个字段,例如:
private final int holderID;
if (holderID == 0) {
holderID = 2213;
// Do other stuff thinking that holderID equals 2213 and no one else will try
// to do the same other stuff, such as updating databases or writing to other
// fields.
}
这确实需要同步。否则,10,000个线程可以同时执行此行(如果您的CPU至少有10,000个核心),请查看holderID中的零,将值设置为自己的数字,并造成严重破坏。但是,从1.5开始,您可以使用java.util.concurrent.atomic包来避免传统的慢速同步。
您必须非常小心最低限度同步的多线程。阅读,思考并设计测试,让所有线程一次只能运行几分钟。使每个类和实例字段不是最终的volatile。永远不要相信类或实例字段。尽快将所有值都放入局部变量中,并尽可能长时间保存在局部变量中。例如,不要这样做:
if (mainList != null) mainList.get( 1 );
某些线程绑定到两个引用之间的null mainList。你可以同步它,但最好这样做:
MainList ml = mainList;
if (ml != null) ml = ml.get( 1 );