你能否告诉我以下调用是否可以重入?
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()
方法获取并释放内部锁,两次调用之间没有嵌套同步。是否存在其他线程可能在两次调用之间发生干扰的情况?
答案 0 :(得分:25)
首先,关于Java中的重入锁:
Java中的同步块是可重入的。这意味着,如果Java线程进入了 同步的代码块,从而锁定监视器对象上的块同步,该线程可以输入同一监视器对象上同步的其他Java代码块。
采取from here。
您描述的两个连续电话(doToo
)将不会受到干扰,除非另一个对象引用Too
的私人Foo
,因为,要访问{ {1}},需要锁定foo
。但是,调用不会调用重新进入,因为每次调用都会获取并释放锁。如果Too
调用doSomething
,反之亦然,它们将是可重入的。
答案 1 :(得分:3)
这完全取决于其他线程正在访问的内容。另一个线程可以在这些函数之间接管CPU吗?是。会有竞争条件吗?取决于很多因素。
从你发布的内容foo.doSomething将被锁定在foo上,然后被释放,然后在进入doAnotherSomething时再次被锁定。因此,如果未锁定在同一个Too对象上的另一个线程试图操纵foo,他们将能够在doSomething和doAnotherSomething之间执行此操作。如果每个人在操作底层foo对象之前在同一个Too对象上进行同步,那么foo的这两个方法将不会在调用之间操纵状态,因为Too对象方法将阻塞其他线程直到完成。因此,如果您有问题,取决于您的其他访问者。
你发布的内容没有重入,但是如果Amir发布,java可以重新同步。
答案 2 :(得分:2)
首先,锁适用于对象,因此需要创建对象然后应用锁。
are 2 continuous invocations in method doToo() reentrant? I
在您的情况下,他们不是可重入的。如果代码类似于下面那么它们将是可重入的。
public class Foo {
public synchronized void doSomething() {
doAnotherSomething();
}
public synchronized void doAnotherSomething() {}
}
一旦在一个物体上获得了锁定,那么就可以在同一物体上进行锁定,就像上面的情况一样。