2016-05-14 3 views
1

Учитывая класс со статическим методом & метод нестатического экземпляра, Как вы убедитесь, что в любой момент времени вызывается только один из этих методов?Как мы можем убедиться, что в любой момент времени вызывается только один из статических методов и нестатический метод класса?

Пример: ------

public class DoMath{ 


public static int getSum(){ 
//Sum 
} 

public int getSub(){ 
//Subtract 
} 

} 

Теперь вы должны убедиться, что в любой момент времени только один из этих методов не вызывается.

ответ

1

Это должно быть сделано.

public class DoMath{ 
    public static synchronized int getSum(){ 
     //Sum 
    } 

    public int getSub(){ 
     synchronized(DoMath.class) { 
      //Subtract 
     } 
    } 
} 

Объяснение: метод static synchronized неявно синхронизирует на Class объект класса, который объявлен метод.

+0

Но можем ли мы сделать блокировку на уровне экземпляра методом экземпляра? –

+0

Да. И это то, что делает моя реализация 'getSub'. –

1

Лучшая практика заключается в использовании частного держателя замка. Это предотвращает блокировку вашего кода вне класса. Это показано в приведенном ниже примере. Обратите внимание на порядок выполнения на выходе - DoMathExposed # getSum() не может вернуться до выхода общедоступного класса монитора. С другой стороны, DoMathEncapsulated # getSum() возвращается сразу же после синхронизации на частном объекте, поэтому сохранение монитора общественного класса не имеет никакого эффекта.

import java.util.concurrent.CountDownLatch; 

public class DoMath { 

    public static void main(String[] args) throws InterruptedException { 

     System.out.println("\nTesting DoMathExposed.class\n"); 
     DoMathExposed.x = 3; 
     DoMathExposed.y = 4; 
     obtainMonitorOf(DoMathExposed.class); 
     System.out.println("Invoked DoMathExposed#getSum()"); 
     System.out.println("DoMathExposed#getSum() returned: " + DoMathExposed.getSum()); 

     System.out.println("\nTesting DoMathEncapsulated.class\n"); 
     DoMathEncapsulated.x = 1; 
     DoMathEncapsulated.y = 2; 
     obtainMonitorOf(DoMathEncapsulated.class); 
     System.out.println("Invoked DoMathEncapsulated#getSum()"); 
     System.out.println("DoMathEncapsulated#getSum() returned: " + DoMathEncapsulated.getSum()); 
    } 

    private static void obtainMonitorOf(final Class cls) throws InterruptedException { 
     final CountDownLatch latch = new CountDownLatch(1); 
     new Thread(new Runnable() { 
      @Override 
      public void run() { 
       synchronized(cls) { 
        System.out.println(cls.getName() + ".class MONITOR held for 10 seconds"); 
        latch.countDown(); 
        try { 
         Thread.sleep(10000); 
        } catch (InterruptedException e) { 
        } 
       } 
       System.out.println(cls.getName() + ".class MONITOR released"); 
      } 
     }).start(); 
     latch.await(); 
    } 
} 


class DoMathEncapsulated { 

    private static final Object lock = new Object(); 

    protected static int x; 
    protected static int y; 

    public static int getSum() { 
     synchronized(lock) { 
      return x + y; 
     } 
    } 

    public int getSub() { 
     synchronized(lock) { 
      return x - y; 
     } 
    } 
} 

class DoMathExposed { 

    protected static int x; 
    protected static int y; 

    public static synchronized int getSum() { 
     return x + y; 
    } 

    public int getSub() { 
     synchronized(DoMathExposed.class) { 
      return x - y; 
     } 
    } 
} 
+0

В чем преимущество объекта блокировки? Я считаю, что вы пытаетесь синхронизировать оба метода с помощью блокировки уровня класса? –

+0

Использование синхронизированного метода или синхронизации на самом объекте DoMath предоставляет держателю блокировки внешний мир. Это означает, что кто-то другой может получить блокировку и заблокировать ваш код. Использование владельца частного замка считается лучшей практикой, поскольку он инкапсулирует поведение блокировки внутри объекта - DoMath в этом случае. – dimplex

+0

Можете ли вы привести мне пример, где я выставил держатель замка на внешний мир, и он стал неправильно использоваться. Любой маленький пример или ресурс действительно поможет понять его, будет полезен и для других, кто может искать его сейчас/в будущем. –