有同步的静态方法和sync'ed非静态方法
好之间没有联系,这是非常简单的说,但如果非静态方法中的代码调用静态方法会怎么样?此线程是否同时保持静态(与类关联)和非静态(与类的实例关联)监视器?
有同步的静态方法和sync'ed非静态方法
好之间没有联系,这是非常简单的说,但如果非静态方法中的代码调用静态方法会怎么样?此线程是否同时保持静态(与类关联)和非静态(与类的实例关联)监视器?
该线程是否同时保持静态(与类关联)和 非静态(与类的实例关联)监视器?
是的,这是因为,
按照Java Language Specification 8.4.3.6,
对于类(静态) 方法中,使用具有用于该方法的 类的Class对象相关联的显示器。对于实例方法,使用与此(调用方法的对象)关联的监视器。
而后所有的2个监视器将单独定义。
没有“静态同步”或“非静态同步”之类的东西。这些想法隐藏了真正发生的事情。
此:
class Foobar {
static synchronized void mumble() { ... }
}
只是为了写这一条捷径:
class Foobar {
static void mumble() {
synchronized(Foobar.class) {
...
}
}
}
而且这样的:
class Foobar {
synchronized void grumble() { ... }
}
只是为了写这一条捷径:
class Foobar {
void grumble() {
synchronized(this) {
...
}
}
}
谈论“静态同步”是没有意义的,因为同步是你对对象做的事情,并且没有静态对象这样的事情。 Java中唯一可以是static
的东西是变量和方法。
P.S.,要回答你的问题,
当一个线程进入一个synchronized块或方法,它必须获得指定对象上的锁,如果线程不已经有对象锁定。因此,如果f.grumble()
在我上面的示例中调用mumble()
,那么线程在进入grumble()例程时必须首先获得f
的锁定,然后在仍然保持该锁定的同时还必须获得Foobar.class
的锁定。
一般来说,当你从一个“同步”模块输入另一个模块(在不同的对象上同步)时,你必须获得两个显示器。(如果代码的另一部分试图以相反的顺序获取相同的两台显示器,那么会出现死锁。) – biziclop