先ほどAtomicMapを使ってみて、いくつか疑問に思ったことがあったので、InfinispanのCacheのトランザクション設定をバリエーションを並べて試してみました。
やったことは、設定的には
- ロック戦略は楽観的、分離レベルはREAD_COMMITTED
- ロック戦略は楽観的、分離レベルはREPEATABLE_READ(バージョンチェック付き)
- ロック戦略は悲観的、分離レベルはREAD_COMMITTED
- ロック戦略は悲観的、分離レベルはREPEATABLE_READ
として、あらかじめデータをCacheに登録のうえ、
- スレッド1、スレッド2がトランザクションを開始
- スレッド1がデータを追加、更新(この間、スレッド2は待ち合わせ)
- スレッド1が、スレッド2に処理を交替
- スレッド2が、スレッド1が更新したデータを参照/上書き、スレッド1が更新していないデータを参照/更新
- スレッド2がコミット
- スレッド2が、スレッド1に処理を交替
- スレッド1がコミット
ということを可能な限りやりました。
条件付きっぽい書き方をしているのは、スレッド2がいろいろ更新したり参照したりする操作は、ものによってはできなかったからです。
まず、スレッド1が更新したデータを参照するのは、どの設定でも不可でした。スレッド1が更新したデータを更新するのは、悲観的ロックの場合は不可でした。
ここでいう不可とは、トランザクションが止まっちゃうということです…。まあ、タイムアウトの設定とか見直せば諦めてくれるんでしょうけど、今回はそこまでやらず。
結果は、悲観的ロックの場合は両スレッドが更新するデータが重ならなければ良し。楽勘的ロックの場合は、REPEATABLE_READ(バージョンチェック付き)の場合は後からコミットしたスレッド1がロールバックされます。READ_COMMITTEDの場合は、後からコミットしたスレッド1の内容で、先にコミットしたスレッド2の変更が上書きされます。
書いたコードは、こちらにアップしておきました。
https://github.com/kazuhira-r/infinispan-examples/tree/master/infinispan-transactions-various