2016-10-16 34 views
1

我有一个如下所示的方法。java同步访问不同的关键部分

public class CriticalSections 
{ 

    public void mainMethod(boolean b) 
     { 
      if (b) { 
       method1(); 
      } 
      else { 
       criticalMethod(); 
       method2(); 
      } 
     } 


     private void criticalMethod() 
     { 
      System.out.println("in criticalMethod"); 
     } 

     private void method1() 
     { 
      System.out.println("in method1"); 
     } 

     private void method2() 
     { 
      System.out.println("in method2"); 
     } 
} 

我需要限制访问这些方法使得

  1. 当criticalMethod()由一个线程,获得方法1()和method2访问()应被用于所有其他线程的限制。同样,当线程访问method1()和method2()时,对所有其他线程的访问都应该受到限制。
  2. method1()可以单独由不同的线程同时访问。方法2()可以单独由不同的线程同时访问。
  3. 可以通过不同的线程同时访问method1()和method2()。

为了满足第一次访问条件,我想出了下面的代码, 但是这并不能满足其他3个条件,因此性能将会受到冲击。

public class CriticalSections 
{ 

    private final Lock lock1 = new ReentrantLock(); 
    private final Lock lock2 = new ReentrantLock(); 
    private final Lock lock3 = new ReentrantLock(); 

    public void mainMethod(boolean b) 
    { 
     if (b) { 
      lock1.tryLock(); 
      try { 
       method1(); 
      } 
      finally { 
       lock1.unlock(); 
      } 
     } 
     else { 
      lock1.tryLock(); 
      try { 
       lock2.tryLock(); 
       try { 
        lock3.tryLock(); 
        try { 
         criticalMethod(); 
        } 
        finally { 
         lock3.unlock(); 
        } 
       } 
       finally { 
        lock2.unlock(); 
       } 
      } 
      finally { 
       lock1.unlock(); 
      } 
     } 
     lock3.tryLock(); 
     try { 
      method2(); 
     } 
     finally { 
      lock3.unlock(); 
     } 
    } 

    private void criticalMethod() 
    { 
     System.out.println("in criticalMethod"); 
    } 

    private void method1() 
    { 
     System.out.println("in method1"); 
    } 

    private void method2() 
    { 
     System.out.println("in method2"); 
    } 
} 

什么应该是用于满足上述场景的同步机制?

回答

3

你需要的是在criticalMethod上的独占锁和方法method1method2上的共享锁。实现这一目标的最简单方法是如下使用java.util.concurrent.locks.ReentrantReadWriteLock

public class CriticalSections { 
    private final ReadWriteLock lock = new ReentrantReadWriteLock(); 

    public void mainMethod(boolean b) { 
     if (b) { 
      method1(); 
     } else { 
      criticalMethod(); 
      method2(); 
     } 
    } 

    private void criticalMethod() { 
     Lock writeLock = lock.writeLock(); 
     writeLock.lock(); 
     try { 
      System.out.println("in criticalMethod"); 
     } finally { 
      writeLock.unlock(); 
     } 
    } 

    private void method1() { 
     Lock readLock = lock.readLock(); 
     readLock.lock(); 
     try { 
      System.out.println("in method1"); 
     } finally { 
      readLock.unlock(); 
     } 
    } 

    private void method2() { 
     Lock readLock = lock.readLock(); 
     readLock.lock(); 
     try { 
      System.out.println("in method2"); 
     } finally { 
      readLock.unlock(); 
     } 
    } 
} 

如果你担心性能,你也可以take a look atjava.util.concurrent.locks.StampedLock(Java的8+)。

+0

谢谢你的回答,一般来说,当存在一个复杂的问题,涉及访问多个关键部分的条件时,应该采取什么样的方法来确保满足所有条件并确保其工作没有任何死锁等),你有什么指针? – themanwhosoldtheworld

+0

在你的代码中,在try块之前,它应该是锁定readLock = lock.readLock(); readLock.lock(); – themanwhosoldtheworld

+0

@themanwhosoldtheworld:感谢您的纠正。我修复了代码片段。 – korolar