2013-09-27 32 views
5

在Collection框架中,为什么外部同步比内部同步更快(Vector,HashTable等)?即使他们都使用相同的机制?为什么外部同步比内部更快?

内部和外部同步的确切含义以及它们如何相互区别?

如果有人可以用例子来解释,这真的很有帮助。

+2

轻微抛开:通常比使用同步集合编写线程安全代码要好得多。 (例如,无锁并发数据结构,在无需阻止时会产生最小开销。) – millimoose

回答

9

内部和外部同步究竟有什么意义,它们又有什么不同?

外部同步是当呼叫者(你)使用​​关键字或其它锁,以防止另一个类被多个线程访问。如果有问题的课程通常使用而不是本身同步 - SimpleDateFormat是一个最好的例子。如果您需要线程之间的信号传输,即使在处理并发收集时也可以使用它。

为什么外部同步比内部同步更快(Vector,HashTable等)?即使他们都使用相同的机制?

外部同步是而不是必然更快。通常,一个类可以精确地确定何时需要围绕代码的关键部分进行同步,而不是调用方包含​​块中的所有方法调用。

如果你在谈论一般建议使用VectorHashTable,转而使用Collections.synchronizedList(...)synchronizedMap(...)方法,那么这是因为VectorHashTable被看作是旧的/旧的过时的类。被包装的ArrayListHashMap被视为更好的解决方案。

有时候,正如@Chris指出的那样,当您需要对一个接一个的类进行一些更改时,外部同步可以更快。通过外部锁定一次,然后对类进行多重更改,这比内部锁定的每个更改都更好。一次锁定比多次锁定呼叫更快。

如果有人可以用例子来解释,这真的很有帮助。

而不是Vector,人们通常建议包装ArrayList作为更好的性能。这将非同步的ArrayList类封装在一个包装类中,该类将其与外部同步。

List<Foo> list = Collections.synchronizedList(new ArrayList<Foo>()); 

在与一般的外部内部条件,认为要允许多个线程同时使用了下列类:

public class Foo { 
    private int count; 
    public void addToCount() { 
     count++; 
     log.info("count increased to " + count); 
    } 
} 

你可以使用外同步和每一个电话换到addToCount()在​​块:

synchronized (foo) { 
    foo.addToCount(); 
} 

或者类本身可以使用内部同步哟做锁定ü。

public void addToCount() { 
    int val; 
    synchronized (this) { 
     val = ++count; 
    } 
    // this log call should not be synchronized since it does IO 
    log.info("count increased to " + val); 
} 

当然,Foo类确实应该在这种情况下使用AtomicInteger和照顾自己的重入内:

因为记录类没有被锁的一部分。这性能更好
private final AtomicInteger count = new AtomicInteger(0); 
public void addToCount() { 
    int val = count.incrementAndGet() 
    log.info("count increased to " + val); 
} 
+0

感谢您使用良好的示例进行探索...... – Rajeev

7

假设你在银行工作。每次需要使用保险箱时,都需要解锁,然后在完成使用后重新锁定。

现在我们假设您需要携带50个箱子进入保险箱。你有两个选择:

  1. 携带每箱过单独开放和每次
  2. 锁的前门银行关闭(极重型)门,离开金库打开,请50个车次无触摸内部金库门

哪一个更快? (第一个选项是内部同步,第二个选项是外部同步。)

+0

好的类比,但如果您需要退出银行每一次。你不能锁定城市或国家 – Mordan

+0

@Mordan我认为你把这个比喻拉得太远了。电脑上的抽象化并不完全受到市政府的阻碍。 Java JVM就是一个很好的例子 - 当它们进行垃圾收集时,它们的一些实现会执行“停止世界”锁定,从而防止所有事情从运行到完成。我并不是说你应该为此而努力,但这并非闻所未闻。 –

相关问题