Java 为什么外部同步比内部同步快?
在集合框架中,为什么外部同步比内部同步(向量、哈希表等)快?即使他们都使用相同的机制 内部同步和外部同步的确切含义是什么?它们之间有什么区别 如果有人能举例说明,那真的很有帮助 内部同步和外部同步的确切含义是什么?它们之间有什么区别 外部同步是指调用方(您)使用Java 为什么外部同步比内部同步快?,java,multithreading,synchronization,Java,Multithreading,Synchronization,在集合框架中,为什么外部同步比内部同步(向量、哈希表等)快?即使他们都使用相同的机制 内部同步和外部同步的确切含义是什么?它们之间有什么区别 如果有人能举例说明,那真的很有帮助 内部同步和外部同步的确切含义是什么?它们之间有什么区别 外部同步是指调用方(您)使用synchronized关键字或其他锁来防止另一个类被多个线程访问。如果所讨论的类本身没有同步,通常会使用它--SimpleDateFormat就是一个很好的例子。如果需要在线程之间发送信号,甚至在处理并发集合时,也可以使用它 为什么外部
synchronized
关键字或其他锁来防止另一个类被多个线程访问。如果所讨论的类本身没有同步,通常会使用它--SimpleDateFormat
就是一个很好的例子。如果需要在线程之间发送信号,甚至在处理并发集合时,也可以使用它
为什么外部同步比内部同步(向量、哈希表等)快?即使他们都使用相同的机制
外部同步不一定更快。通常,类可以准确地确定何时需要围绕关键代码段进行同步,而不是调用方将所有方法调用包装在synchronized
块中
如果您讨论的是一般性建议,即不要使用Vector
和HashTable
,而是使用集合.synchronizedList(…)
或synchronizedMap(…)
方法,那么这是因为Vector
和HashTable
被视为旧的日期类。包装的ArrayList
或HashMap
被视为更好的解决方案
有时正如@Chris指出的,当您需要一个接一个地对类进行大量更改时,外部同步可以更快。通过在外部锁定一次,然后对类执行多个更改,这比在内部锁定每个更改效果更好。一个锁比一行中的多个锁调用更快
如果有人能举例说明,那真的很有帮助
人们通常推荐包装的ArrayList
,而不是Vector
,因为它具有更好的性能。这会将非同步的ArrayList
类包装在一个外部同步的包装器类中
List<Foo> list = Collections.synchronizedList(new ArrayList<Foo>());
您可以使用外部同步,并将对addToCount()
的每个调用包装在同步的
块中:
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);
}
假设你在银行工作。每次你需要使用保险箱时,它都需要解锁,然后在使用完毕后重新锁定 现在让我们假设你需要携带50个箱子进保险箱。您有两个选择:
哪一个更快?(第一个选项是内部同步,第二个选项是外部同步。)Minor旁白:通常有比使用同步集合更好的方法来编写线程安全代码。(例如,无锁并发数据结构,在不需要阻塞时产生最小的开销。)很好的类比,但如果每次都需要离开银行,则外部数据结构是不好的。你不能封锁城市,也不能封锁城市country@Mordan我认为你把这个比喻说得有点过分了。计算机上的抽象并不完全受到市政当局的阻碍。Java JVM就是一个很好的例子——当它们进行垃圾收集时,它们的一些实现会执行“停止世界”锁定,这实际上会阻止一切运行,直到完成为止。我并不是说你应该为此而努力,但这并非前所未闻。
private final AtomicInteger count = new AtomicInteger(0);
public void addToCount() {
int val = count.incrementAndGet()
log.info("count increased to " + val);
}