同期化

通常、サーブレット開発者はサーブレット インスタンスとの関連で同期化を認識していますが、実際の作業を実行するのはスレッドです。多くのスレッドが同時に実行されることもあります。

各インスタンスは複数のスレッドで実行される可能性があるため、オブジェクトスコープ変数やその他の共有リソースでの同期化の問題を認識する必要があります。同期化とは、1 つのコードをシングルスレッドとして実行させることです。スレッド管理は、JMC を使用して、各 JVM に別々のスレッド パラメータを指定することによって制御します。


メモ

スレッド管理は高度な操作であるため、本書では扱いません。詳細については、Java スレッド管理に関する市販の解説書を参照してください。


クラススコープ インスタンス変数の同時アクセスを防止するには多くの方法があります。以下はその例です。

次のサブセクションでこれらのテクニックについて説明します。

メソッド シグネチャでの synchronized キーワードの使用

メソッド シグネチャで synchronized キーワードを使用することで、メソッド全体へのアクセスを同期化できます。

...
public class TestCaller extends HttpServlet
{
  int visitorCounter = 0;

  // コンセプトの説明のみを目的とした例なので、実際には実行しないでください。
public synchronized void doGet(HttpServletRequest servReq, 
  HttpServletResponse servRes) throws IOException, ServletException { 
...

メモ

この例は、コンセプトについて説明するためのものです。この同期化テクニックは パフォーマンスを低下させるため、実際にはほとんど使用しません。


同期化されたコードの使用

synchronized されたブロックを使用して、オブジェクトスコープ変数へのアクセスを同期化することができます。

...
int thisCount;
synchronized(this) {
  // visitorCount はオブジェクトスコープ変数です。
  thisCount = visitorCounter++;
}
out.println("<p>You are visitor number " + thisCount);
...

この例では、同期化されたブロック内のカウンタを増分し、それによってオブジェクトスコープ変数へのシングルスレッド アクセスを保証します。

SingleThreadModel インターフェイスの使用

SingleThreadModel インターフェイスは JRun に一群のサーブレット インスタンスを作成して、それぞれのインスタンスについて同時スレッドが service メソッドを実行しないように指示します。

...
public class testSync extends HttpServlet
  implements SingleThreadModel {
...

JRun は SingleThreadModel を実装するサーブレットの複数のインスタンスを作成するため、オブジェクトスコープ インスタンス変数がすべてのインスタンスについて同じでなければならない場合、このテクニックは使用できません。たとえば、このテクニックをヒット カウンタには使用できません。しかし、オブジェクトスコープインスタンス変数を使用しないサーブレットの場合、またはオブジェクトスコープ インスタンス変数が異なってもよい場合 (例 : バッファ変数、データベース接続) には、SingleThreadModel は効果的なテクニックです。

オブジェクトスコープ変数にアクセスするメソッドの同期化

オブジェクトスコープ変数へのすべてのアクセスが同期化されたメソッドによって行われるようなアクセス方式を実装できます。

...
public class TestSync extends HttpServlet {
  int visitorCounter = 0;

public void doGet(HttpServletRequest req, HttpServletResponse res)
  throws IOException, ServletException { 
    incrementCount();
...
public synchronized void incrementCount() {
  visitorCount++;
}
public synchronized int getCount() {
  return visitorCount;
}
...