1

サーバーが一度に 1 つのクライアントに対して、サービス impl コードの特定の部分をスレッドセーフに実行するようにしたい。そして順次。これを行うサーバー側サービス実装の一部を次に示します。

public BorcData getBorcData(String userId) throws GeneralException, EyeksGwtException
{
        StoredProcedure sp = DALDB.storedProcedure("BORCBILDIRIM_GETMUKDATA_SP");
        DALResult spResult;
        Row spRow;
        String vergiNo;
        String asamaOid;

        synchronized (ServerUtility.lock_GeriArama_GetBorcData_GetMukDataSP)
        {
            String curOptime =CSDateUtility.getCurrentDateTimeToSave();

            sp.addParam(curOptime);
            spResult = sp.execute();

            if (!spResult.hasNext())
            {
                throw new GeneralException("53", "");
            }
        }

同期ブロックが表示されます。ロックに使用するオブジェクトは次のように定義されています。

public static Object lock_GeriArama_GetBorcData_GetMukDataSP = new Object();

私の問題は、クライアントがその同期ブロックの実行を長時間待っている間に、他のクライアントがこのサービスを呼び出して、列に並ばずにそのブロックを実行して続行したことを見たと思います。最初のクライアントはまだ待っていました。

サーバー側で純粋な Java が実行されていることは知っています。サーバー側がクライアントに対して不公平であり、最も長く待機しているクライアントの要求を最初に実行していない可能性はありますか?

編集:実際には; 公平性は本当の問題でさえありません。時々、クライアントはその同期部分にぶら下がっているように見えます。サービスが終了するのを永遠に待っています。

4

2 に答える 2

3

最初に、常にロック オブジェクトを宣言する必要がありますfinal。これは問題を解決するものではありませんが、何か間違ったコードを作成したかどうかがわかります (ロックを別のロックに設定するなど)。

公平性を確保する 1 つの方法は、true で初期化されたReentrantLockを使用することです (公平なスケジューリング)。クライアントが無期限にハングしないようにしますが、FIFO の順序で実行されます。良いことは、これらすべての同期ブロックを次のように置き換えることで、コードを少し変更するだけで済むことです。

lock.lock();
try { 
  // previous code
} finally {
  lock.unlock();
}

最終的には、内部のいずれかの部分が例外をスローした場合の安全対策です。

それ以外は、コードは完全に問題ないように見えるため、問題は DB にある可能性が高く、同期を使用したことが原因ではありません。

于 2013-11-11T13:37:21.363 に答える