代码之家  ›  专栏  ›  技术社区  ›  Gandalf StormCrow

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

  •  6
  • Gandalf StormCrow  · 技术社区  · 15 年前

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

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

    8 回复  |  直到 15 年前
        1
  •  8
  •   gustafc    15 年前

    在特定对象(指定的静态锁对象或类对象)上进行同步(当静态方法声明为同步时会发生这种情况):

    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 这种方法允许您通过将lock字段设置为private来禁止它(这样可以更容易地对锁定进行推理,并避免您的代码因为其他人编写了错误的代码而死锁)。

    当然,您也可以使用 java.util.concurrent Lock s、 提供更多的锁定控制(和 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);
    

    现在 foo bar 仍然相互联系,但可以独立工作 frob quux .

        2
  •  5
  •   NG.    15 年前

    private static final Object STATIC_LOCK = new Object();
    
    private void foo() {
         synchronized (STATIC_LOCK) {
              //do stuff...
         } 
    }
    
        3
  •  2
  •   jdehaan    15 年前

    你可以用静电笔 Mutex 在那个方法里面。因此,任何并发线程都在方法内部阻塞,而另一个线程则在运行它,无论它属于类的哪个对象。我不认为有任何特殊的单一关键字,以产生像这样的效果 synchronized .

        4
  •  2
  •   David J. Liszewski    15 年前

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

    synchronized(MyClass.class) {
            // mutually excluded method body
    }
    
        5
  •  1
  •   calavera.info    15 年前

    两个线程都必须使用此结构

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

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

        6
  •  0
  •   florin    15 年前

    这没有内在的机制。创建自己的静态锁属性,并确保在每个方法中锁定和解锁它。别忘了例外-确保在“最终”部分解锁它。

        7
  •  0
  •   Janick Bernet    15 年前

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

    “误用”类的运行时表示进行锁定。这是可能的,因为在Java中任何对象都可以用作互斥对象。

        8
  •  0
  •   neal aise    15 年前

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

    讨论了实现它的几种方法。 一般来说,锁是禁止性的,会阻碍线程的好处。因此,关键代码应该尽可能地最小化。

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