Thread Safe Class许多方法ReentrantLock

时间:2015-01-02 15:35:19

标签: java multithreading

我有一个控制器类如下:

public class Controller {
    private Driver driver;

    public void method1() {/**/}
    public void method2() {/**/}
    public void method3() {/**/}
}

每种方法都使用driver执行某些操作。 method2是一个运行时间较长的进程,需要锁定driver,因为如果其他方法在driver运行时使用method2,则会发生错误。

现在我正在设置的方式,我在控制器的调用类中实现了一个ReentrantLock公平调度,它负责线程安全,如下所示:

public class Caller {
    private static final Lock LOCK = new ReentrantLock(true);

    private Controller controller;

    public void startStuff() { // Runs in multiple threads.
        ...
        ...
        LOCK.lock();
        try {
            controller.method1();
        } finally {
            LOCK.unlock();
        }
        ...
        ...
        LOCK.lock();
        try {
            controller.method2();
        } finally {
            LOCK.unlock();
        }
   }
}

我想改为使Controller类线程安全,而不是让任何调用类处理它。我假设这样做的方法是在每个方法的开头和结尾实现try-finally块,但我在类中有大约15个方法。这真的是这样做的吗?这似乎是一吨样板代码:

public class Controller {
    private static final Lock LOCK = new ReentrantLock(true);
    private Driver driver;

    public void method1() {
       LOCK.lock();
       try {
           /**/
       } finally {
           LOCK.unlock();
       }
    }
    public void method2() {
       LOCK.lock();
       try {
           /**/
       } finally {
           LOCK.unlock();
       }
    }
    public void method3() {
       LOCK.lock();
       try {
           /**/
       } finally {
           LOCK.unlock();
       }
    }
}

我不能只为每个方法添加synchronized,因为我需要公平的日程安排才能使应用程序正常工作,并且使用ReentrantLock可以很好地工作。

如何使用Controller确保ReentrantLock类线程安全?

1 个答案:

答案 0 :(得分:4)

您可以将锁定代码包装到一个块中,并将实际的代码实现传递给它,以便删除复制/样板。类似于以下内容(Java 7):

public void method1() {
   withLock(new LockableMethod() {
       public void run() {
           /** your method1 code here **/
       }
   });
}

private void withLock(LockableMethod lockableMethod) {  
   LOCK.lock();
   try {
       lockableMethod.run();
   } finally {
       LOCK.unlock();
   }
}

如果您正在使用Java 8,只需传入Lambda即可删除更多样板文件:

public void method1() {
   withLock(() -> { 
           /** your method1 code here **/
       }
   );
}

private void withLock(Consumer<T> consumer) {
    LOCK.lock();
    try {
        consumer.accept();
    } finally {
        LOCK.unlock();
    }
}