1

I want to submit tasks to a ForkJoinPool or ParallelArray from a thread holding a write lock. Access to our domain model is protected by checks that the current thread holds the relevant lock. To allow FJ workers to perform tasks on it (read only, e.g. querying), they need to delegate access checks to the thread that spawned them.

I subclassed the ForkJoinWorkerThread with a reference to the spawning thread. I then subclassed ReentrantReadWriteLock and overrode isWriteLockedByCurrentThread to perform the usual check, and fall back to a check that, if the thread is an instance of the delegating FJWorker, that the delegate thread (parent) is the owner of the lock, using 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;
    }
}

However, the documentation for getOwner() states the following:

When this method is called by a thread that is not the owner, the return value reflects a best-effort approximation of current lock status. For example, the owner may be momentarily null even if there are threads trying to acquire the lock but have not yet done so.

I would like to understand this to mean that if I've submitted the tasks within a thread that has already been granted access, this method will correctly return the reference to it. Unfortunately, this is not even implied.

If I can't use this method, what other alternatives exist for this kind of delegation?

Thank you.

sms1
  • 83
  • 7

1 Answers1

0

I imagine that the implementation details of getOwner() are such that if there is a happens-before relationship between the thread that acquired the write lock and the thread querying the owner, that it will have determinstic behaviour that ensures the correct owner is returned. I have not checked the implementation, but it feels like this is what the comments are alluding to, and are covering the base that the behaviour can be non-deterministic while the lock is being acquired.

However, it may be easier all around if it is possible for you to downgrade your write lock and avoid all of the delegation checking to begin with (since then each thread could own its own read lock). Perhaps it is also possible to use two separate locks, say an outer and inner lock, where the inner lock is not held for writing in this case?

Edit: The implementation of getOwner() calls getState() which does a read of the volatile state variable, and this should be enough to guarantee that getOwner() will always return your parent thread if it holds the write lock.

Trevor Freeman
  • 7,112
  • 2
  • 21
  • 40
  • The submitting thread acquires a write lock from the outset because it's not possible to upgrade from a read to write lock later on. Any FJ task that requires read access (running within separate FJ pool threads) will be blocked by the write lock of the submitting thread, unless it can delegate access checks to it, which is what I'm trying to achieve. – sms1 Mar 02 '12 at 01:13
  • @sms1 I checked the implementation of getOwner(), and it does a read on getState which ensure volatile read semantics (reads volatile state variable). This should be enough to ensure that if the exclusive write lock is held by your parent thread, then subsequent calls to getOwner will deterministically return the parent thread instance. – Trevor Freeman Mar 02 '12 at 01:33
  • Definitely, submissions will occur after acquiring the lock. I've read the code initially but the docs wording undermined my confidence in the memory semantics in this case. I think the doc example preclude this situation, so I think you're correct. Thank you. – sms1 Mar 02 '12 at 02:06