TL;博士 - 外部同步打开你去攻击(有意或无意),和也迫使你锁定可能不需要的检查。在这个答案的底部还有一些书呆子好的信息。
一个synchronized方法是几乎相同(参见下图)就此同步:
synchroinzed void foo() {
}
void foo() {
synchronized(this) {
}
}
通过使本身不,你让自己锁定在任何Object
的方法,而不仅仅是this
。我个人会建议同步在内部Object
,像这样
private final Object foolock = new Object();
void foo() {
synchronzied(foolock) {
}
}
的原因是,如果你做一个方法,从而有效地锁定this
别人能synchronize
对你和你锁在外面你Object
的!想象一下:
class FooDoer {
// removed! using synchronized methods instead
//final Object foolock = new Object();
synchronized void foo() {
}
}
// thread 1 - attacker
FooDoer f = new FooDoer();
globalMap.put("TheFoo",f);
synchronized(f) {
while(true); // haha!
}
// thread 2 - victim
FooDoer f = globalMap.get("TheFoo");
f.foo(); // locked, because Thread 1 has locked us out!
它打开了自己的拒绝服务攻击。这不好!通过将锁置于内部,您作为类的作者可以准确控制谁可以锁定对象的哪些区域以及在哪些条件下。
另一个问题是您可能没有受保护的数据进行检查。例如:
synchronized void foo() {
if(expensiveAccessCheck()) {
update();
}
}
void foo() {
if(expensiveAccessCheck()) {
synchronized(foolock) {
update();
}
}
}
在这种情况下,您不必让其他人等你坐在那里旋转轮子。也许你是从一个URL中取出数据然后更新。为什么其他人不能锁定数据?在这种情况下,粒度越低越好。
现在你可能还记得我之前说过的几乎完全相同。两者之间有微小的差别。一个同步的方法将烘烤指令,以正确地同步字节码中的方法签名。这将使字节码1字节缩短,因为它不需要进行额外的呼叫。这可能会产生很小的影响,因为方法字节码中的字节数是确定是否内联的因素之一。尽管有这样的细节,我强烈建议将它们视为相同,因为这是一种微型优化,在生产环境中几乎不会发挥重要作用。当它们不是完全相同时,就称它为完全相同的。
感谢柯克回答了这个问题。我知道同步方法和synchronized(this)之间的区别。但我想知道更多关于同步方法vs同步(对象定义)。 –
'syncrhonized(this)'和'synchronized(other object)'之间的唯一区别就是你正在同步的对象。 –
换句话说,每个Java对象都有一个隐藏的锁定字段,“synchronized”语句/块可以获取。所有Java'synchronized'方法和块都获取某个对象上的锁定字段。他们只是因为他们如何决定要做哪个对象而有所不同。 –