OSCacheの並列性バグ
OSCache-2.4.1 にて、同一キーに対して並列に複数の操作を行い、ある条件を満たすとバグります。
例外は、
Exception in thread "Thread-2" java.lang.IllegalStateException: Cannot complete cache update - current state (2) is not UPDATE_IN_PROGRESS
のようなのが出ます。
例外は、下記のソース中の、Stack Trace 1, Stack Trace 2, Stack Trace 3 のとおりに各スレッドを進めると発生します。
ソース
import com.opensymphony.oscache.general.GeneralCacheAdministrator; import com.opensymphony.oscache.hibernate.OSCache; /** * Test for oscache-2.4.1. "current state (2) is not UPDATE_IN_PROGRESS" * * @author beyondseeker * @version $Id$ */ public class Main { public static void main(String[] args) throws Exception { GeneralCacheAdministrator gca = new GeneralCacheAdministrator(); final OSCache cache = new OSCache(gca, -1, null, "hoge"); // This thread creates updateState and increments updateState.nbConcurrentUses. // // ******** Stack Trace 1 ******** // Thread [Thread-0] (Suspended) // Cache.getFromCache(String, int, String) line: 261 // GeneralCacheAdministrator.getFromCache(String, int, String) line: 173 // OSCache.get(Object) line: 42 // Main$1.run() line: 16 // ******************************* new Thread() { public void run() { cache.get("a"); }}.start(); // This thread changes the state of updateState UPDATE_CANCELLED. // // ******** Stack Trace 2 ******** // Thread [Thread-1] (Suspended) // Cache.cancelUpdate(String) line: 422 // GeneralCacheAdministrator.cancelUpdate(String) line: 184 // OSCache.get(Object) line: 45 // Main$2.run() line: 26 // ******************************* new Thread() { public void run() { cache.get("a"); }}.start(); // This thread throws IllegalStateException since updateState is not UPDATE_IN_PROGRESS but UPDATE_CANCELLED. // // ******** Stack Trace 3 ******** // Thread [Thread-2] (Suspended) // EntryUpdateState.completeUpdate() line: 105 // Cache.completeUpdate(String) line: 797 // Cache.putInCache(String, Object, String[], EntryRefreshPolicy, String) line: 641 // Cache.putInCache(String, Object, String[]) line: 614 // GeneralCacheAdministrator.putInCache(String, Object, String[]) line: 270 // OSCache.put(Object, Object) line: 54 // Main$3.run() line: 36 // ******************************* new Thread() { public void run() { cache.put("a", "foo"); }}.start(); } }
例外
Exception in thread "Thread-2" java.lang.IllegalStateException: Cannot complete cache update - current state (2) is not UPDATE_IN_PROGRESS at com.opensymphony.oscache.base.EntryUpdateState.completeUpdate(EntryUpdateState.java:105) at com.opensymphony.oscache.base.Cache.completeUpdate(Cache.java:797) at com.opensymphony.oscache.base.Cache.putInCache(Cache.java:641) at com.opensymphony.oscache.base.Cache.putInCache(Cache.java:614) at com.opensymphony.oscache.general.GeneralCacheAdministrator.putInCache(GeneralCacheAdministrator.java:270) at com.opensymphony.oscache.hibernate.OSCache.put(OSCache.java:54) at Main$3.run(Main.java:22)