2012-08-31 45 views
2

你能告诉我下面的调用是否可重入吗?可重入同步

public class Foo { 

    public synchronized void doSomething() {} 

    public synchronized void doAnotherSomething() {} 
} 

public class Too { 

    private Foo foo; 

    public synchronized void doToo() { 
    foo.doSomething(); 
    //...other thread interfere here.... 
    foo.doAnotherSomething(); 
    } 

} 

是方法doToo()中的2个连续调用重入?我不知道这种情况,因为foo.doSomething()方法获取并释放内部锁,2个调用之间没有嵌套同步。其他线程是否可能会干扰2个调用之间的情况?

回答

2

这完全取决于其他线程正在访问什么。另一个线程可以在这些函数之间接管CPU吗?是。会有比赛条件吗?取决于很多因素。

从您发布的内容foo.doSomething将被锁定在foo上,然后释放,然后在进入doAnotherSomething时再次锁定。所以如果另一个线程没有锁定在同一个Too对象上,试图操纵foo,他们就可以在doSomething和doAnotherSomething之间这样做。如果在操作底层foo对象之前每个人都在同一个Too对象上同步,那么这两个foo方法将不会在调用之间操作状态,因为Too对象方法会阻塞其他线程直到完成。因此,如果你有问题,取决于你的其他访问器。

您发布的内容不存在再入,但是Java在Amir发布后可以重入同步。

+0

我发现你的答案对我来说很清楚!谢谢 – MinhHoang

15

首先,关于Java的可重入锁:

在Java的synchronized块折返。这意味着,如果Java线程输入一个代码同步代码块,并因此取得监视器对象上的锁定,则同步该块,该线程可以输入在同一监视器对象上同步的其他Java代码块。

拍摄from here

你(在doToo)中所描述的两个连续通话不会被干扰,除非有另外一个对象来的Too私人Foo一个参考,因为访问foo,一个需要锁定Too。但是,这些调用不会调用重入,因为每次调用都会获取并释放锁。如果doSomething调用doAnotherSomething,则它们将是可重入的,反之亦然。

1

首先,所有锁都适用于对象,因此需要创建对象并应用锁。

are 2 continuous invocations in method doToo() reentrant? I

在你的情况下,他们不会重入。如果代码如下所示,那么它们将会重入。

public class Foo { 

public synchronized void doSomething() { 
     doAnotherSomething(); 
} 

public synchronized void doAnotherSomething() {} 
} 

一旦锁定已经获得一个对象,然后在同一个对象,它可以遍历像上面的情况。

+0

解释@amirs点的示例,谢谢 – VedX