サーブレットスレッドのセキュリティ

5107 ワード

質問:servletのスレッドセキュリティの問題を以下のコードで説明しますか?
 1 public class MultiThreadQuestion extends HttpServlet {
 2     public int count = 0;
 3     public void doGet(HttpServletRequest request, HttpServletResponse response)
 4             throws ServletException, IOException {
 5         // 1.                    
 6         try {
 7             this.count++;
 8             Thread.sleep(5 * 1000);
 9         } catch (InterruptedException e) {
10             e.printStackTrace();
11         }
12         response.getOutputStream().write(("   :"+Thread.currentThread().getName()+"count="+this.      count).getBytes());
13     }
14 }

以上のコードに同時にアクセスすると3回同時に現れることがわかり,これがスレッドの同時アクセスの問題である.
解決策は、同期
共有リソースにアクセスするコードにロックをかけます.
 1 public class MultiThreadQuestion extends HttpServlet {
 2     public int count = 0;
 3     public void doGet(HttpServletRequest request, HttpServletResponse response)
 4             throws ServletException, IOException {
 5         // 1.                    
 6         synchronized (this) {
 7             try {
 8                 this.count++;
 9                 Thread.sleep(5 * 1000);
10             } catch (InterruptedException e) {
11                 e.printStackTrace();
12             }
13             response.getOutputStream().write(("   :"+Thread.currentThread().getName()+"count="+this.count).getBytes());
14         }
15     }
16 }

まとめ:
1.同期キーを直接使用すると、servletの実行効率が大幅に低下します.
2.servletを使用するメンバー変数はできるだけ避けます.
3.避けられない場合は、スレッドの安全なメンバー変数を使用する必要があります.
      ArrayList    Vector    HashSet  
スレッドセキュリティでないコレクションが必要な場合は、Collectionsを使用してスレッドセキュリティの変換を行うことができます.
4.サーブレットContext、HttpSessionが必要な場合は必ず同期を使用してください.
5.servletではローカル変数を使用することが望ましい.