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

Gan*_*row 6 java multithreading

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

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

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

gus*_*afc 8

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

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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


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

而不是像这样的东西:

class Z {
    private static int state;
    public void oneAtATime(){
        synchronized (Z.class) {
            state++;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

像这样做:

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);
Run Code Online (Sandbox Code Playgroud)

现在,foobar仍然依赖于对方,但他们可以从独立工作frobquux.


NG.*_*NG. 5

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

private static final Object STATIC_LOCK = new Object();

private void foo() {
     synchronized (STATIC_LOCK) {
          //do stuff...
     } 
}
Run Code Online (Sandbox Code Playgroud)