Raj*_*eev 5 java multithreading synchronization
在Collection框架中,为什么外部同步比内部同步(Vector,HashTable等)更快?即使他们都使用相同的机制?
内部和外部同步的确切含义以及它们如何彼此不同?
如果有人可以用例子解释,这真的很有用.
内部和外部同步的确切含义以及它们如何彼此不同?
外部同步是指调用者(您)使用synchronized关键字或其他锁来防止多个线程访问的另一个类.如果所讨论的类本身不同步,通常会使用它 - 这SimpleDateFormat是一个很好的例子.如果您需要线程之间的信令,也可以使用它 - 即使在处理并发集合时也是如此.
为什么外部同步比内部同步(Vector,HashTable等)更快?即使他们都使用相同的机制?
外部同步是不是一定会更快.通常,类可以精确地确定何时需要围绕代码的关键部分进行同步,而不是在synchronized块中包含所有方法调用的调用者.
如果您正在讨论不使用Vector和HashTable使用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)
假设你在银行工作.每次需要使用保险箱时,都需要解锁,然后在完成使用后重新锁定.
现在让我们说你需要携带50个盒子进入保险箱.您有两种选择:
哪一个更快?(第一个选项是内部同步,第二个选项是外部同步.)