我想从持有写锁的线程向ForkJoinPool或ParallelArray提交任务。通过检查当前线程持有相关锁来保护对我们的域模型的访问。为了允许FJ工作者在其上执行任务(只读,例如查询),他们需要将访问检查委托给产生它们的线程。
我将ForkJoinWorkerThread子类化为对产生线程的引用。然后我将ReentrantReadWriteLock子类化并覆盖isWriteLockedByCurrentThread以执行常规检查,并回退到检查,如果线程是委派FJWorker的实例,则委托线程(父)是锁的所有者,使用的ReentrantReadWriteLock#getOwner():
public class DelegateAwareReentrantReadWriteLock extends ReentrantReadWriteLock {
@Override
public boolean isWriteLockedByCurrentThread() {
return super.isWriteLockedByCurrentThread() || isWriteLockedByDelegateThread();
}
private boolean isWriteLockedByDelegateThread() {
final Thread currentThread = Thread.currentThread();
if (currentThread instanceof FJAccessDelegatingWorker) {
final Thread delegate = ((FJAccessDelegatingWorker) currentThread).getDelegate();
return delegate.equals(getOwner());
}
return false;
}
}
但是,documentation for getOwner()声明如下:
当a调用此方法时 不是所有者的线程,返回值反映了一个 当前锁定状态的尽力近似。例如, 即使存在,所有者可能暂时无效 线程试图获得锁定但尚未这样做。
我想理解这意味着如果我已经在已经被授予访问权限的线程中提交了任务,则此方法将正确地返回对它的引用。不幸的是,这甚至都没有暗示。
如果我不能使用这种方法,那么这种授权还有哪些替代方案?
谢谢。
答案 0 :(得分:0)
我认为getOwner()的实现细节是这样的:如果获取写锁定的线程与查询所有者的线程之间存在一个先发生的关系,那么它将具有确定正确所有者的确定行为退回。我没有检查过实现,但感觉这就是评论所暗示的内容,并且涵盖了在获取锁定时行为可能是非确定性的基础。
但是,如果您可以降级写锁定并避免所有委托检查开始(从那时起每个线程都可以拥有自己的读锁定),那么可能会更容易。也许也可以使用两个单独的锁,比如外锁和内锁,在这种情况下内锁不能用于书写?
编辑: getOwner()的实现调用getState()来读取volatile状态变量,这应该足以保证getOwner()总是返回你的父线程,如果它持有写锁定。