0

異なるスレッドで使用されるデータベース オブジェクトがあります。

import java.sql.Connection;
import oracle.ucp.jdbc.PoolDataSourceFactory;
import oracle.ucp.jdbc.PoolDataSource;

public class Database
{
  private final PoolDataSource pool = PoolDataSourceFactory.getPoolDataSource();

  protected Connection connect ()
  {
    synchronized (pool) { return pool.getConnection(); }
  }

  protected void disconnect (Connection connection)
  {
    synchronized (pool) { connection.close(); }
  }
}

poolメンバーへのアクセスを同期する必要がありますか? それとも、明示的な同期を回避するだけで十分でしょうか?

disconnect同期が必要な場合、接続を閉じるために呼び出す必要がないため、コードが壊れます。クラスの一部のコードはconnection.close()、同期をバイパスして呼び出すことができます。

4

3 に答える 3

5

一般に、ミューテックスを使用して最終参照へのアクセスを保護するべきではありません。この種のフィールドはJava Memory Modelに従って安全に公開されるためです。

部分的なケースでは、 PoolDataSourceImpl (またはPoolXADataSourceImpl ) で、独自の状態スロー メソッドgetConnection()connection.close();. したがって、 PoolDataSource の実装がスレッドセーフであることを確認する必要があります。したがって、『 Oracle® Database JDBC Developer's Guide and Reference』では、DataSource はスレッドセーフですが、接続ではないように見えます。

Oracle JDBC ドライバーは、Java マルチスレッドを使用するアプリケーションを完全にサポートし、高度に最適化されています。接続キャッシュによって提供されるような、接続への制御されたシリアル アクセスは必要であり、推奨されます。ただし、Oracle では、複数のスレッド間でデータベース接続を共有しないことを強くお勧めします。複数のスレッドが同時に接続にアクセスできるようにしないでください。複数のスレッドが接続を共有する必要がある場合は、統制された使用開始/使用終了プロトコルを使用します。

于 2013-09-20T10:09:16.190 に答える
3

final同期は、フィールドが不変の場合にのみ不要です。final Stringたとえば、sを同期する必要はありません。不変オブジェクトを保持しないこのようなフィールドがある場合でも、オブジェクト自体 ( などPoolDataSource) がスレッドセーフでない限り、同期が必要です。

于 2013-09-20T10:08:34.477 に答える
1

おそらく必要ありません。を使用する必要がある場合、いくつかの理由がありますsynchronized

  1. 変数はスレッド A で変更され、スレッド B で読み取られます。

    finalこれは変数では起こり得ないので、この理由はありません。

  2. いくつかの変数を変更する必要があり、他のスレッドはそれらの変数をまったく認識しないか、すべて認識しなければなりません。

    単一のフィールドへのアクセスは必要ありませんsynchronized

  3. 複合オブジェクトの内部状態を保護する必要があります。Map.put()はそのような場合です。x.put()は 1 回のアクセスにすぎませんが、マップの内部状態の更新はいくつかの変数を変更するため、この場合に必要ですsynchronized

    質問は次のとおりです。またはのために必要ですpool.getConnection()connection.close()

    これに対する答えは、使用するライブラリ/フレームワークのドキュメントにあります。

一般的に言えば、接続プールはマルチスレッド アプリケーションの接続プールを保持するために作成されたものであるため、ユーザー側でロックすることなく安全に呼び出すことができます。

于 2013-09-20T10:35:51.683 に答える