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)