Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么外部同步比内部同步快?_Java_Multithreading_Synchronization - Fatal编程技术网

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个箱子进保险箱。您有两个选择:

  • 单独搬运每个箱子,每次打开和关闭(非常重的)门
  • 锁上银行前门,保持保险库打开,在不接触内部保险库门的情况下进行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);
    }