2012-09-12 159 views
0

可能重复:
synchronized block vs synchronized method?方法同步vs对象同步有什么不同?

如果有人可以帮助我什么是同步VS同步对象的方法之间的不同实际的例子?这将是很好。

方法进行同步例

public class MyClassExample { 
private int i; 
public synchronized void increment(){ 
    i = i + 1; 
} 
} 

对象同步示例

public class MyClassExample { 
private int i; 
Object writeLock = new Object(); 
public void increment(){ 
    synchronized(writeLock) { 
     i = i + 1; 
    } 
} 
} 

回答

3

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字节缩短,因为它不需要进行额外的呼叫。这可能会产生很小的影响,因为方法字节码中的字节数是确定是否内联的因素之一。尽管有这样的细节,我强烈建议将它们视为相同,因为这是一种微型优化,在生产环境中几乎不会发挥重要作用。当它们不是完全相同时,就称它为完全相同的。

2

甲​​实例方法同步上this

所以

public synchronized void increment(){ 
    i = i + 1; 
} 

相当于

public void increment(){ 
    synchronized (this) { 
     i = i + 1; 
    } 
} 
+0

感谢柯克回答了这个问题。我知道同步方法和synchronized(this)之间的区别。但我想知道更多关于同步方法vs同步(对象定义)。 –

+0

'syncrhonized(this)'和'synchronized(other object)'之间的唯一区别就是你正在同步的对象。 –

+0

换句话说,每个Java对象都有一个隐藏的锁定字段,“synchronized”语句/块可以获取。所有Java'synchronized'方法和块都获取某个对象上的锁定字段。他们只是因为他们如何决定要做哪个对象而有所不同。 –

2

Java语言规范writes

甲同步方法获取监视器它执行(§17.1)之前。

对于类(静态)方法,使用与方法类的Class对象关联的监视器。

对于实例方法,使用与this(为其调用方法的对象)相关联的监视器。

这些是可以由同步声明(§14.19)中使用的相同的显示器。

因此,代码:

class Test { 
    int count; 
    synchronized void bump() { 
     count++; 
    } 
    static int classCount; 
    static synchronized void classBump() { 
     classCount++; 
    } 
} 

正好有相同的效果:

class BumpTest { 
    int count; 
    void bump() { 
     synchronized (this) { count++; } 
    } 
    static int classCount; 
    static void classBump() { 
     try { 
      synchronized (Class.forName("BumpTest")) { 
       classCount++; 
      } 
     } catch (ClassNotFoundException e) {} 
    } 
} 
+0

感谢您的回答。但我的问题是不同的。问题是我想知道更多关于同步方法vs synchronized(对象定义)。 –

+0

*您的问题与您的问题有何不同?既然它们具有“完全相同的效果”,我可以给予什么客观的标准来支持另一个呢? – meriton