【问题标题】:why external synchronization is faster than internal one?为什么外部同步比内部同步快?
【发布时间】:2013-09-27 16:07:09
【问题描述】:

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

内部和外部同步的确切含义以及它们之间的区别是什么?

如果有人可以举例说明,那真的很有帮助。

【问题讨论】:

  • 次要:通常有比使用同步集合更好的方法来编写线程安全代码。 (例如,在不需要阻塞时产生最小开销的无锁并发数据结构。)

标签: java multithreading synchronization


【解决方案1】:

内部和外部同步的确切含义以及它们之间的区别是什么?

外部同步是调用者(您)使用synchronized 关键字或其他锁来防止另一个类被多个线程访问。如果所讨论的类本身同步,则通常使用它——SimpleDateFormat 就是一个很好的例子。如果您需要在线程之间发出信号,也可以使用它——即使在处理并发集合时也是如此。

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

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

如果您谈论的一般建议使用VectorHashTable,而是使用Collections.synchronizedList(...)synchronizedMap(...) 方法,那么这是因为Vector 和@ 987654329@ 被视为旧的/过时的类。封装的 ArrayListHashMap 被视为更好的解决方案。

有时正如@Chris 所指出的,当您需要一个接一个地对一个类进行大量更改时,外部同步会更快。通过在外部锁定一次然后对类执行多次更改,这比在内部锁定每个更改更好。单个锁比连续调用多个锁要快。

如果有人可以举例说明,那真的很有帮助。

人们通常推荐使用包装好的 ArrayList 而不是 Vector,因为它具有更好的性能。这会将非同步的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();
}

或者类本身可以使用内部同步并为您进行锁定。这执行得更好,因为 logger 类不必是锁的一部分:

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);
}

【讨论】:

    【解决方案2】:

    假设您在一家银行工作。每次您需要使用保险箱时,都需要将其解锁,然后在使用完毕后重新上锁。

    现在假设您需要将 50 个箱子放入保险箱。你有两个选择:

    1. 单独搬运每个箱子,每次打开和关闭(非常重的)门
    2. 锁上银行的前门,让金库保持打开状态,在不接触金库内部门的情况下完成 50 次旅行

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

    【讨论】:

    • 好类比,但如果您每次都需要离开银行,那么外部就不好了。你不能锁城也不能锁国
    • @Mordan 我认为你的比喻有点过分了。计算机上的抽象并没有完全受到市政当局的阻碍。 Java JVM 就是一个很好的例子——当他们进行垃圾收集时,他们的一些实现会执行“停止世界”锁定,这实际上会阻止一切运行,直到它完成。我并不是说你应该为此而努力,但这并非闻所未闻。
    猜你喜欢
    • 1970-01-01
    • 2015-08-29
    • 2017-05-18
    • 1970-01-01
    • 2014-01-21
    • 2014-01-08
    • 1970-01-01
    • 2021-12-08
    • 1970-01-01
    相关资源
    最近更新 更多