线程安全 Class 许多方法 ReentrantLock
Thread Safe Class Many Methods ReentrantLock
我有一个控制器class如下:
public class Controller {
private Driver driver;
public void method1() {/**/}
public void method2() {/**/}
public void method3() {/**/}
}
每个方法都使用 driver
来执行某些操作。然而,method2
是一个运行时间较长的进程,需要锁定 driver
,因为如果其他方法在 method2
运行时使用 driver
,则会发生错误。
现在按照我目前的设置方式,我在控制器的调用 class 中实现了一个 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
class 线程安全,而不是让任何调用 classes 处理它。我假设要完成的方法是在每个方法的开头和结尾实现 try-finally 块,但我在 class 中有大约 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
效果很好。
如何使用 ReentrantLock
使 Controller
class 线程安全?
您可以将锁定代码包装到一个块中,并将实际的代码实现传递给它,这样您就可以删除 duplication/boilerplate。类似于以下内容 (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();
}
}
我有一个控制器class如下:
public class Controller {
private Driver driver;
public void method1() {/**/}
public void method2() {/**/}
public void method3() {/**/}
}
每个方法都使用 driver
来执行某些操作。然而,method2
是一个运行时间较长的进程,需要锁定 driver
,因为如果其他方法在 method2
运行时使用 driver
,则会发生错误。
现在按照我目前的设置方式,我在控制器的调用 class 中实现了一个 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
class 线程安全,而不是让任何调用 classes 处理它。我假设要完成的方法是在每个方法的开头和结尾实现 try-finally 块,但我在 class 中有大约 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
效果很好。
如何使用 ReentrantLock
使 Controller
class 线程安全?
您可以将锁定代码包装到一个块中,并将实际的代码实现传递给它,这样您就可以删除 duplication/boilerplate。类似于以下内容 (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();
}
}