投機的実行をやってみたやつで、synchronizedを使ってたのだけど、ReadWriteLockを使ったほうが並列可能性が高くなるかもね、と思ってちょっと修正してみた。
ところで、最後のロックを次のように、ReadLockの中でWriteLock取得しようと思ったんだけど、デッドロックしてしまったようだ。
こういう再入はできないらしい。
Lock rlock = lock.readLock(); try{ rlock.lock(); if(modified.get()){ if(version != readVer.get()){ //変更されている continue; } Lock wlock = lock.writeLock(); try{ wlock.lock(); value = myValue.get(); version++; }finally{ wlock.unlock(); } } }finally{ rlock.unlock(); }
ということで、こんな感じ
public static class TransactionalInteger{ static ReadWriteLock lock = new ReentrantReadWriteLock(); int value; final ThreadLocal<Integer> myValue = new ThreadLocal<Integer>(); final ThreadLocal<Integer> readVer = new ThreadLocal<Integer>(); final ThreadLocal<Boolean> modified = new ThreadLocal<Boolean>(); int version = 0; public TransactionalInteger() { } public TransactionalInteger(int value) { this.value = value; } int get() { return myValue.get(); } void set(int o) { myValue.set(o); modified.set(true); } void flush(){ Lock rlock = lock.readLock(); try{ rlock.lock(); myValue.set(value); readVer.set(version); modified.set(false); }finally{ rlock.unlock(); } } void with(final Runnable runner) { for(;;) { flush(); runner.run(); Lock wlock = lock.writeLock(); try{ wlock.lock(); if(modified.get()){ if(version != readVer.get()){ //変更されている continue; } value = myValue.get(); version++; } }finally{ wlock.unlock(); } break; } } }