通常、サーブレット開発者は、サーブレットインスタンスとの関連で同期化を認識していますが、この作業を実行するのはスレッドです。多くのスレッドが同時に実行されることもあります。
各インスタンスは複数のスレッドで実行される可能性があるため、オブジェクトスコープ変数などの共有リソースを使用する同期化で起こり得る問題を認識する必要があります。同期化とは、1 つのコードをシングルスレッドのように実行させることです。スレッド管理は、JMC を使用し、各 JVM に別々のスレッドパラメータを指定して制御します。
メモ: スレッド管理は高度な内容であるため、このマニュアルでは説明しません。詳細については、Java スレッド管理に関する市販の解説書を参照してください。
クラススコープのインスタンス変数への同時アクセスを防止するには多くの方法があります。次に例を示します。
SingleThreadModel
インターフェイスを実装します。synchronized
を doXxx
メソッドの署名に含めます (この方法はお勧めしません)。これらのテクニックについては、次のサブセクションで説明します。
メソッド署名で 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); ...
この例では、synchronized
ブロック内でカウンタを増分し、それによってオブジェクトスコープ変数へのシングルスレッドアクセスを保証します。
次の例に示すように、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; } ...