是否可以从另一个线程调用锁定对象的方法?

时间:2011-10-02 11:20:47

标签: java concurrency

当线程1由于

而具有对象的固有锁定时
synchronized(object) {
...
}

是否可以致电

object.method()

从线程2分别是否需要输入

synchronized(object) {
object.method();
}
线程2中的

是为了防止它在线程1持有锁时调用该方法?

在我的情况下,我在迭代Map时得到了ConcurrentModificationExceptions,我试图通过锁定地图来阻止来自其他线程的修改。我知道ConcurrentModificationExceptions的原因通常是迭代期间地图被更改但我很确定在我的情况下不是这种情况,因为在迭代中只有“get”-statements和一个方法调用,所以不可能有任何修改。

提前致谢。

Binabik

3 个答案:

答案 0 :(得分:1)

Java中的同步是完全合作的 - 如果第二个线程没有选择尝试获取监视器(并且如果方法中没有尝试这样做的话),那么它将不会自动锁定。

并不是对象“被锁定” - 这是一个线程拥有与该对象关联的锁。对象本身仍然可以访问;如果它不需要锁,它就不会阻塞。

请注意,如果您尝试迭代它并在同一循环内更改它,即使在单个线程中也可以获得ConcurrentModificationException,例如。

// Not safe: will throw an exception
for (Map.Entry<String, String> entry : map.entrySet()) {
    if (entry.getKey().equals("foo")) {
        map.put("bar", "Hello");
    }
}

这可能是您的代码中发生的事情,但我们无法分辨,因为您没有显示我们任何代码。如果你能提出一个简短而完整的程序来证明这个问题,那么我们就更有可能找出正在发生的事情。

答案 1 :(得分:1)

获取锁定时,它只会阻止其他线程获取相同的锁定。它不会像这样锁定对象,您可以访问它的方法。

如果遇到ConcurrentModicationException,则会进行并发修改。如果你不知道发生了什么,你需要进一步调查。

答案 2 :(得分:0)

除非同步object.method(),否则可以从其他线程调用它。在非同步映射上使用迭代时必须小心。您应该使用同步映射并在迭代中进行同步;否则你也必须同步所有的写操作。