Java文档说“同一个对象上的两个同步方法的调用不可能交错”。我需要知道的是,synchronized是否还会阻止同一类的两个不同实例中的同步方法进行交错。
E.g。 class Worker有一个名为process()的方法。我们有几个Worker在自己的线程中运行的实例。我们希望防止同时运行process()方法的多个实例。 synchronized 会这样做吗?
感谢。
答案 0 :(得分:26)
没有; synchronized
仅阻止多个线程同时执行相同实例中的方法。如果您有 n 个实例,则可能有 n 个线程,每个线程都在其中一个实例中执行该方法。
如果您需要确保只有一个线程可以在所有实例中执行该方法,那么您应该使用方法static
,或者使方法不是synchronized
而是使用synchronized
阻止方法内部锁定private static
字段。
编辑:请注意,在private
实例变量上进行同步比使用synchronized
方法或在this
上进行同步以及锁定private static
实例变量更受欢迎最好使用static synchronized
方法或在this.getClass()
上同步的实例方法。原因是this
和this.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()