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

Raj*_*eev 5 java multithreading synchronization

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

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

如果有人可以用例子解释,这真的很有用.

Gra*_*ray 9

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

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

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

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

如果您正在讨论使用VectorHashTable使用Collections.synchronizedList(...)synchronizedMap(...)方法的一般建议,那么这是因为Vector并且HashTable被视为旧的/旧的类.包裹ArrayList或被HashMap视为更好的解决方案.

有时正如@Chris指出的那样,当您需要对一个接一个的类进行一些更改时,外部同步会更快.通过外部锁定一次然后对类执行多次更改,这比每次在内部锁定的更改效果更好.单个锁比多个锁调用快一行.

如果有人可以用例子解释,这真的很有用.

而不是Vector,人们通常建议包装ArrayList具有更好的性能.这将非同步ArrayList类包装在外部同步它的包装类中.

List<Foo> list = Collections.synchronizedList(new ArrayList<Foo>());
Run Code Online (Sandbox Code Playgroud)

一般而言,就内部与外部而言,请考虑以下要允许多个线程同时使用它的类:

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

您可以使用外部同步并将每个调用包装addToCount()在一个synchronized块中:

synchronized (foo) {
   foo.addToCount();
}
Run Code Online (Sandbox Code Playgroud)

或者类本身可以使用内部同步并为您执行锁定.这样做效果更好,因为记录器类不必是锁的一部分:

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);
}
Run Code Online (Sandbox Code Playgroud)

当然,在这种情况下,Foo班级真的应该使用一个AtomicInteger并在内部照顾自己的重入:

private final AtomicInteger count = new AtomicInteger(0);
public void addToCount() {
    int val = count.incrementAndGet()
    log.info("count increased to " + val);
}
Run Code Online (Sandbox Code Playgroud)


Chr*_*rle 7

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

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

  1. 每个箱子单独携带,每次打开和关闭(极重)门
  2. 将前门锁定到银行并使保险库打开,在不触及内部金库门的情况下进行50次行程

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