1

我想从持有写锁的线程向 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;
    }
}

但是,getOwner() 的文档说明了以下内容:

当不是所有者的线程调用此方法时,返回值反映了当前锁定状态的最大努力近似值。例如,即使有线程试图获取锁但尚未这样做,所有者也可能暂时为空。

我想理解这意味着如果我在已被授予访问权限的线程中提交任务,此方法将正确返回对它的引用。不幸的是,这甚至没有暗示。

如果我不能使用这种方法,这种委托还有哪些其他选择?

谢谢你。

4

1 回答 1

0

我想 getOwner() 的实现细节是这样的,如果在获取写锁的线程和查询所有者的线程之间存在发生之前的关系,它将具有确定性的行为,以确保返回正确的所有者。我没有检查实现,但感觉这就是评论所暗示的,并且涵盖了在获取锁时行为可能是非确定性的基础。

但是,如果您可以降级您的写锁并避免所有委托检查开始(因为那时每个线程都可以拥有自己的读锁),那么这可能会更容易。也许也可以使用两个单独的锁,比如一个外锁和一个内锁,在这种情况下,内锁不用于写入?

编辑: getOwner() 的实现调用 getState() 读取 volatile 状态变量,这应该足以保证 getOwner() 如果它持有写锁,它将始终返回您的父线程。

于 2012-03-02T01:04:39.337 回答