0

次のコードの参照が他のトランザクションと同様に以下のトランザクションで変更されていると仮定すると、私の懸念は、このトランザクションがコミットの時間になるまで実行され、コミットに失敗してからトランザクションを再実行することです。

(defn modify-ref [my-ref]
  (dosync (if (some-prop-of-ref-true @my-ref)
            (alter my-ref long-running-calculation))))

これが私の恐れの全容です:

  1. modify-ref が呼び出され、トランザクションが開始され (A と呼びます)、長時間実行計算が開始されます。
  2. 別のトランザクション (B と呼びます) が開始され、my-ref が変更され、返されます (正常にコミットされます)。
  3. long-running-calculation は終了するまで継続します
  4. トランザクション A はコミットを試みますが、my-ref が変更されているため失敗します
  5. some-prop が true でないため、トランザクションは my-ref の新しい値で再開され (A' と呼びます)、終了します。

これが私が起こりたいことであり、おそらくこれが起こることです(私にはわからないので、質問しています:-)

トランザクション B が my-ref をコミットしたら、トランザクション A をすぐに停止して (my-ref の値が変更されたため)、新しい値で再開したいと考えています。それが起こるのですか?

この動作が必要な理由は、長時間実行計算が、現在は廃止された計算で CPU 時間をすべて浪費しないようにするためです。

を使用することを考えensureましたが、このコンテキストでどのように使用するか、または必要かどうかわかりません。

4

2 に答える 2

3

それはあなたが恐れているように機能します。

JVM で実行中のスレッドを停止するには、共同作業が必要になるため、Clojure (または他の JVM 言語) が実行中の計算を停止する一般的な方法はありません。計算は定期的に信号をチェックして、それ自体を停止する必要があるかどうかを確認する必要があります。Java でスレッドを強制終了する方法を参照してください。.

どうやって実装するかというと、難しすぎるので、本当に問題になるかどうかをまず測定します。そうであれば、従来の悲観的ロックがより良い解決策であるかどうかを確認します。悲観的なロックがまだ解決策でない場合は、トランザクションの外部で計算を実行し、ref でウォッチャーを使用し、計算後に条件付きで ref を設定するものを構築しようとします。もちろん、これはトランザクションの境界の外で実行され、おそらくそれが聞こえるよりもはるかにトリッキーです。

についてensureは、変更されている参照のみがトランザクションに参加するため、書き込みスキューが発生する可能性があります。より長い説明については、Clojure STM のあいまい性要因を参照してください。

于 2014-08-09T12:26:59.413 に答える