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() のドキュメントには次のように記載されています。

このメソッドが所有者ではないスレッドによって呼び出された場合、戻り値は現在のロック ステータスのベスト エフォート近似を反映します。たとえば、ロックを取得しようとしているがまだ取得していないスレッドがある場合でも、所有者が一時的に null になることがあります。

これは、既にアクセスが許可されているスレッド内でタスクを送信した場合、このメソッドがそのスレッドへの参照を正しく返すことを意味することを理解したいと思います。残念ながら、これは暗示されていません。

この方法を使用できない場合、この種の委任には他にどのような方法がありますか?

ありがとうございました。

4

1 に答える 1

0

getOwner() の実装の詳細は、書き込みロックを取得したスレッドと所有者を照会するスレッドとの間に発生前の関係がある場合、正しい所有者が返されることを保証する決定論的な動作を持つようになっていると思います。私は実装をチェックしていませんが、これはコメントがほのめかしているように感じ、ロックが取得されている間、動作が非決定論的である可能性があるというベースをカバーしています.

ただし、書き込みロックをダウングレードし、最初からすべての委譲チェックを回避できる場合は、全体的に簡単になる可能性があります (各スレッドが独自の読み取りロックを所有できるため)。おそらく、2 つの別個のロック、たとえば外部ロックと内部ロックを使用することも可能であり、この場合、内部ロックは書き込みのために保持されませんか?

編集: getOwner() の実装は、揮発性状態変数の読み取りを行う getState() を呼び出します。これは、書き込みロックを保持している場合、getOwner() が常に親スレッドを返すことを保証するのに十分なはずです。

于 2012-03-02T01:04:39.337 に答える