繁体   English   中英

如何使用synchronized锁定整个类的方法?

[英]How to lock a method for a whole class using synchronized?

我知道当你想要锁定方法时只用一个线程来执行你用synchronized关键字声明它。

那么类,当线程在该类的实例上执行某些代码时,如何提供对整个对象类的锁定呢?

换句话说,当一个线程在一个对象上执行一个方法时,即使在同一个类的不同实例上也不应该允许其他线程执行相同的方法。

您在特定对象上同步,可以是某个指定的静态锁定对象,也可以是类对象(当声明静态方法被同步时会发生):

class X {
    private static final Object lock = new Object();
    public void oneAtATime() {
        synchronized (lock) {
            // Do stuff
        }
    }
}
class Y {
    public void oneAtATime() {
        synchronized (Y.class) {
            // Do stuff
        }
    }
}

每个变体都有自己的优点和缺点; 锁定类允许类之外的其他代码出于其自身原因使用相同的锁(这允许它协调比您提供的更高级别的同步),而static final Object lock方法允许您通过使锁定字段保密(这使得更容易推断锁定并避免代码死锁,因为其他人编写了错误的代码)。

您当然也可以使用java.util.concurrent一些同步机制,例如显式Lock ,它提供对锁定的更多控制(并且ReentrantLock当前比高争用下的隐式锁定执行得更好)。


编辑:请注意,静态/全局锁定不是一个好方法 - 这意味着所创建的类的每个实例都将基本上绑定到每个其他实例(除了使测试或读取代码更加困难之外,严重损害可扩展性)。 我假设你这样做是为了同步某种全局状态? 在这种情况下,我会考虑在类中包装该全局/静态状态,并实现每个实例的同步而不是全局。

而不是像这样的东西:

class Z {
    private static int state;
    public void oneAtATime(){
        synchronized (Z.class) {
            state++;
        }
    }
}

像这样做:

class State {
    private int value;
    public synchronized void mutate(){ value++; }
}
class Z {
    private final State state;
    public Z(State state){
        this.state = state;
    }
    public void oneAtATime(){
        state.mutate();
    }
}
// Usage:
State s1 = new State(), s2 = new State();
Z foo = new Z(s1);
Z bar = new Z(s1);
Z frob = new Z(s2);
Z quux = new Z(s2);

现在foobar仍然相互联系,但他们可以独立于frobquux

如果使用静态同步方法,则通过类锁定锁定它们。 你也可以在类中声明一个静态Object,并在我相信的方法中将其锁定,例如:

private static final Object STATIC_LOCK = new Object();

private void foo() {
     synchronized (STATIC_LOCK) {
          //do stuff...
     } 
}

您可以在该方法中使用静态Mutex 所以任何并发线程都在方法内阻塞,而另一个并发运行它,无论它属于哪个类的对象。 我不认为有任何特殊的单一关键字可以产生像synchronized一样的效果。

这是一个相当积极的同步,我会尽可能地避免它。

在类的静态字段或类本身上同步:

synchronized(MyClass.class) {
        // mutually excluded method body
}

两个线程都必须使用这种结构

public void someMethod() {
  synchronized(ClassThatShouldBeProtected.class) {
    someSynchronizedCode();
  }
}

这种方法得益于这样一个事实,即类本身是一个对象,因此它有一个监视器。 那你就不需要任何人工静态实例了。

没有内置的机制。 创建自己的静态锁属性,并确保锁定它并在每种方法中解锁它。 不要忘记异常 - 确保在“finally”部分解锁。

这应该工作:

public class MyClass {
  void synchronizedMethod() {
    synchronized (MyClass.class) {
       // synchronized on static level
    }
  }
}

哪个'错过'类的锁定运行时表示。 这是可能的,因为任何对象都可以用作Java中的互斥锁。

http://www.janeg.ca/scjp/threads/synchronization.html

谈谈实现它的几种方法。 通常,锁是禁止的并且阻碍了线程的好处。 因此,关键代码应尽量减少。

你想要一个类杠杆锁来访问类的静态变量,还是要保护对类的公共外部资源的访问? 在这种情况下,您应该在访问它时有一个单独的锁。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM