同步关键字 - 它是否锁定两个对象



假设我有两个哈希映射hashMap1和hashMap2,以及一个多线程并发Java程序。如果我放置一个同步块

synchronized(hashMap1) {
hashMap1.put(5, "Hello");
hashMap2.put(10, "Hi");
}

由于一次只有一个线程可以访问hashMap1,那么只有一个线程可以访问hashMap2吗?我本质上是在问 hashMap2 是否会像 hashMap1 一样受到保护,防止多个线程同时访问它。

谢谢!

不,synchronized不会"锁定对象"。你的代码块所做的是要求线程在进入块之前对hashMap1进行锁定。hashMap1 本身没有以任何方式"锁定",除了它的监视器正在被获取。(也许称它为显示器比称它为锁更清楚。监视器是所有对象都具有的东西,它本身不会做任何事情来控制对它所属对象的访问。如果在其他地方访问hashMap2,这个同步块不会做任何事情来阻止这种情况。

同步块的目的是要求线程获取监视器。您希望保护该资源免受并发访问的所有位置都需要使用相同的锁。它是受synchronized保护的代码块,告诉何时需要使用锁定对象来控制访问。

监视器的选择可以与被保护以防止并发访问的实际对象分开。您可以拥有一个专用的锁对象并使用它,不需要您必须在要保护的东西上使用锁。(唯一的优点是它可能有助于组织,如果您只访问一个东西,那么使用该东西的显示器可能会很方便。使用专用锁可能更清晰:

public class Foo {
    private final Object LOCK = new Object();
    private Map hashMap1 = new HashMap();
    private Map hashMap2 = new HashMap();
    public void doStuff() {
        synchronized(LOCK) {
            ... // do stuff with hashMap1 and hashMap2
        }
    }
}

保持对锁的访问对对象保密意味着对象可以限制谁可以获取锁(与synchronized(this)不同(。也不要使用字符串或布尔值之类的东西,这些东西可以被扣留、缓存或以其他方式从程序的其他部分访问。

答案取决于您的应用程序设计。毕竟,同步是一个选择加入的概念 - 任何线程都可以选择忽略锁并简单地访问共享对象。

与您的

示例类似,如果您确定对hashMap2的唯一访问是在示例中所示的同步块内,那么您正在使用锁有效地保护它,尽管锁定了另一个对象。

对于未来的维护者来说,在对它们进行操作之前对这两个对象进行锁定可能会更清楚。

synchronized 关键字会导致线程在进入方法时获取锁,只有一个线程可以同时执行该方法(对于给定的对象实例,除非它是静态方法(。

在您的情况下,只要 synchronized 方法内部是修改 hashmap2 的唯一地方,那么是的,它将受到保护,防止多个线程同时访问。但是,如果 hashmap2 在 synchronized 方法内部之外的其他地方被修改,则不能保证 hashmap2 将受到保护。

最新更新