synchronized关键字 - 它是否锁定了两个对象?

时间:2014-12-10 14:08:31

标签: java multithreading synchronized

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

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

由于只有一个线程可以访问hashMap1,只有一个线程能够访问hashMap2吗?我本质上是在询问hashMap2是否会受到多个线程的保护,一次访问它就像hashMap1一样。

谢谢!

3 个答案:

答案 0 :(得分:4)

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

synchronized块的目的是要求线程获取监视器。您希望保护该资源免受并发访问的所有位置需要采用相同的锁。这是用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)不同)。也不要使用可以从程序的其他部分实习,缓存或以其他方式访问的字符串或布尔值等内容。

答案 1 :(得分:0)

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

与您的示例类似,如果您确定hashMap2的唯一访问权限位于示例中显示的synchronized块中,那么您实际上是通过锁定来保护它,尽管锁定了另一个对象。

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

答案 2 :(得分:0)

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

在您的情况下,只要在synchronized方法内部是唯一修改了hashmap2的地方,那么就可以保护它免受多个线程一次访问的影响。但是,如果除了synchronized方法内部之外的其他地方正在修改hashmap2,则无法保证hashmap2将受到保护。