关于Java同步的问题

时间:2011-06-02 12:00:20

标签: java synchronization

Java文档说“同一个对象上的两个同步方法的调用不可能交错”。我需要知道的是,synchronized是否还会阻止同一类的两个不同实例中的同步方法进行交错。

E.g。 class Worker有一个名为process()的方法。我们有几个Worker在自己的线程中运行的实例。我们希望防止同时运行process()方法的多个实例。 synchronized 会这样做吗?

感谢。

7 个答案:

答案 0 :(得分:26)

没有; synchronized仅阻止多个线程同时执行相同实例中的方法。如果您有 n 个实例,则可能有 n 个线程,每个线程都在其中一个实例中执行该方法。

如果您需要确保只有一个线程可以在所有实例中执行该方法,那么您应该使用方法static,或者使方法不是synchronized而是使用synchronized阻止方法内部锁定private static字段。

编辑:请注意,在private实例变量上进行同步比使用synchronized方法或在this上进行同步以及锁定private static实例变量更受欢迎最好使用static synchronized方法或在this.getClass()上同步的实例方法。原因是thisthis.getClass()是可在整个程序中访问的对象引用,因此任何人都可以在这些对象上进行同步,从而阻止想要调用方法的线程。

编辑:另外,请参阅下面的@Cugan评论 - 摘要:如果你真的想锁定课程,你可能想要使用synchronized (Worker.class)而不是synchronized (this.getClass()),这取决于你想要的效果子类化的情况。

答案 1 :(得分:3)

不,同步不会这样做。更具体地说,在实例级别上同步不会这样做。相反,您必须在班级上进行同步。

例如,而不是:

public synchronized method()
{
    //do stuff
}

您必须编码为:

public void method()
{
    synchronized(this.getClass())
    {
        //do stuff
    }
}

答案 2 :(得分:2)

除非方法是static,否则不会。 synchronized非静态方法对调用它的对象(实例)进行锁定,而不对类进行锁定。

同步静态方法会对类进行锁定,因此可能有所帮助 - 但它通常不太实用。

你可以做的是在你的类中有一个静态成员对象,并在process方法中对该(类 - 全局)对象执行同步块。

答案 3 :(得分:2)

不,该方法同步锁定特定对象('this'),因此同一类的2个实例将锁定不同的对象。

如果要跨类的所有实例进行同步,则需要在方法中使用synchronized块,锁定静态最终对象。

答案 4 :(得分:0)

如果将方法process设为静态,则只允许同时调用该方法。

如果无法做到这一点,请使用静态变量,比如Integer lock; 并在方法synchronized (lock)中使用process

process()
{
    synchronized (lock)
    {

        // all your code

    }
}

答案 5 :(得分:0)

我对Aasmund略有不同意见 - 虽然同时有点同意: 如果你使用这样的结构:

class Worker {
...
 public synchronized void process() {...}
}

然后Aasmund是对的 - 这不会阻止Worker类的多个实例并行执行process()。 但是,您可以使用synchronized关键字仍然在静态成员上进行同步,以防止发生这种情况:

class Worker {
 static Object o = new Object();
 ...
 public void process() {
  synchronized(o) {
   ...//perform the work here
  }
 }

答案 6 :(得分:0)

任何时候只有一个线程可以锁定对象。

同步方法尝试保持对实例的锁定。另一个线程也可以锁定同一个类的另一个实例。另一个线程无法进入同一实例的另一个同步方法。即它不是被锁定的方法。

但是,一个线程可以进入非同步方法,而另一个线程持有该对象的锁。只有同步的方法受到保护。

静态同步方法获取Class而不是对象的锁。但是,除非使用不同的对象,否则遵循与非静态方法相同的规则。

注意:即使您可以编写似乎使用实例的代码,静态方法也没有“实例”。例如instance.staticMethod()

相关问题