2016-05-14 25 views

回答

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

你能否举个例子说明我的锁具是否暴露在外部世界,并且它被滥用了。任何小例子或资源都将有助于理解它,对其他人来说也是有益的,他们可能正在寻找现在/将来。 –

相关问题