[DBFLUTE-207] {Java}: 初期化処理が同時に走ると処理が途中で停止することがある Created: 2008-02-18  Updated: 2008-03-01  Resolved: 2008-02-25

Status: Closed
Project: DBFlute
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: skirnir Assignee: jflute
Resolution: Fixed Votes: 0
Labels: None
Environment:

DBFulute 0.5.7-SNAPSHOT



 Description   

アプリケーションを起動した後、複数スレッドからDaoのメソッドを同時に呼び出すなどしてDBFlute(&S2Dao)の初期化処理を同一タイミングで走らせるようにすると、処理が途中で停止することがある。

具体的には、Webアプリケーションで起動して最初に同時アクセスを行なったところ、ConditionBeanContext#addColumnAliasInfo()の156行目で処理が停止してしまった。

原因は以下のように推測される:

なおデバッガを仕掛けて追っていくことができない環境だったため、上記仮説が正しいかは不明です。



 Comments   
Comment by jflute [ 2008-02-18 ]

DaoMetaDataFactoryの対応だけS2Dao-1.0.47のみ対応とします。
(ちょっと他のバージョンではシンプルな実現が難しそうなため)

Comment by jflute [ 2008-02-18 ]

ご報告ありがとうございます。

ソースを追っかけたところ、その他怪しい部分が幾つかありました。

  • S2DaoのSqlCommand
  • SeasarのBeanDescImpl (S2Daoで使っている)
    そのことから、基本的にDaoの初期化処理自体を同期化したいと思います。
    // DaoMetaDataFactory
    public DaoMetaData getDaoMetaData(final Class daoClass) {
        if (!initialized) {
            DisposableUtil.add(this);
            initialized = true;
        }
        final String key = daoClass.getName();
		
		// [A]
        DaoMetaData dmd = getSynchronizedDaoMetaDataCache(key);
		
		// [B]
        if (dmd != null) {
            return dmd;
        }
		
		// [C]
		synchronized (_daoMetaDataInitializationLockMonitor) {// One Thread Only Entered
		    // [D]
		    dmd = getSynchronizedDaoMetaDataCache(key);
			// [E]
			if (dmd != null) {
			    // The second thread that stops at [C] can find
				// because the first thread have already initialized.
				if (_log.isDebugEnabled()) {
				    _log.debug("...Getting daoMetaData as cache because the previous thread have already initilized.");
				}
                return dmd;
            }
			// [F]
			if (_log.isDebugEnabled()) {
			    _log.debug("...Initializing daoMetaData.");
			}
            final DaoMetaData dmdi = createDaoMetaData(daoClass);
			putSynchronizedDaoMetaDataCache(key, dmdi);
		}
		// [G]
	    dmd = getSynchronizedDaoMetaDataCache(key);
        if (dmd != null) {
			if (_log.isDebugEnabled()) {
			    _log.debug("...Confirming that daoMetaData have been certainly initialized and cached.");
			}
            return dmd;
        }
		String msg = "The cache should have data meta data here: key=" + key + " cache=" + daoMetaDataCache;
        throw new IllegalStateException(msg);
    }

    // DaoMetaData
    public SqlCommand getSqlCommand(String methodName) throws MethodNotFoundRuntimeException {
        SqlCommand cmd = (SqlCommand) sqlCommands.get(methodName);
        if (cmd != null) {
            return cmd;
        }
        if (_internalDebug) {
            _log.debug("...Initializing sqlCommand: " + methodName);
        }
		synchronized (_methodInitializationLockMonitor) {
			cmd = (SqlCommand) sqlCommands.get(methodName);
            if (cmd != null) {
                return cmd;
            }
            cmd = initializeSqlCommand(methodName);
		}
		return cmd;
    }
Generated at Mon Dec 15 07:55:07 JST 2025 using Jira 10.6.1#10060001-sha1:a6461e220f274b29ced7ac9295492f2465fe5ef5.