为什么外部同步比内部同步更快?

时间:2013-09-27 16:07:09

标签: java multithreading synchronization

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

内部和外部同步的确切含义以及它们彼此之间有何不同?

如果有人可以用例子解释,那将非常有用。

2 个答案:

答案 0 :(得分:9)

  

内部和外部同步的确切含义以及它们彼此之间有何不同?

外部同步是指调用者(您)使用synchronized关键字或其他锁来防止多个线程访问的另一个类。如果有问题的类自身同步,通常会使用它 - SimpleDateFormat是一个主要的例子。如果您需要线程之间的信令 - 即使在处理并发集合时也可以使用它。

  

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

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

如果您正在讨论使用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块中的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); } 并在内部处理它自己的重入:

{{1}}

答案 1 :(得分:7)

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

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

  1. 每个盒子单独携带,每次打开和关闭(极重)门
  2. 将前门锁定到银行并保持金库打开,在不触及内部金库门的情况下进行50次旅行
  3. 哪一个更快? (第一个选项是内部同步,第二个选项是外部同步。)