小编典典

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

java

我知道当您想锁定仅由一个线程执行的方法时,可以使用synchronized关键字声明它。

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

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


阅读 222

收藏
2020-11-16

共1个答案

小编典典

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

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方法允许您通过设置锁定字段来禁止使用它私有(这样可以更轻松地推断出锁定状态,避免由于其他人编写的错误代码而导致代码死锁)。

当然,您也可以使用from的一些同步机制java.util.concurrent,例如explicit
Locks,它提供了对锁定的更多控制(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仍然相互联系,但是它们可以独立于frob和进行工作quux

2020-11-16