finerss's world!

동기화 +1

동기화

공부/Sevlets&JSP2011. 6. 29. 10:32
컨텍스트 속성 애플리케이션에 있는 누구든지 접근할수 있다는 것을 잊으면안된다.

다양한 서블릿들과 하나의 서블릿이 멀티스레드로 실행되고 있는 환경에서

Context속성에 들어온 요청이 동일한 서블릿으로 온것인지 다른서블릿으로 온것인지

컨테이너는 구분하지 못한다.

어떤 한 서블릿이 Context속성의 값을 변경/사용 하고있더라도

다른 서블릿이 속성 값을 마음대로 변경/사용 할수있는 것이다.

컨테스트에 락을 걸자!

컨텍스트 속성을 보호하는 가장 전형적인 방법은 컨텍스트 객체 자체를 동기화(lock)하는 방법이다.

컨텍스트에 가장 먼저 접근한 객체가 컨텍스트에 락을 건다.

이렇게 하는것은 특정 시점에서 오직 하나의 스레드만이 컨텍스트 속성을 설정하거나 값을 읽는 것을 보장한다는 의미이다.

그러나 여기에도 조건은 있다.

동일 컨텍스트 속성을 다루는 모든 코드들이 마찬가지로 ServletContext에 대하여 락을 걸어야 이것이 작동한다는 것이다.

만약 어떤 코드는 락을 요청하지 않았다면, 여전히 컨텍스트 속성에 자유롭게 접근할수 있기떄문이다.

이를 방지하기위해 웹 애플리ㅔ이션 설계 시 모든 개발자들이 속성에 접근하기 전에 강제적으로 락을 걸도록 만들어야 한다.

밑에 소스를 보면

public void doGet(HttpServletRequest request, Http ServletResponse response)
                                                                    throws IOException, ServletException){
             response.setContentType("Text/html");
             printWriter out = response.getWriter();

             out.println("test context attributes<br>");

        synchronized(getServletContext()){
         //컨텍스트 속성을 보호하기위해 컨텍스트 자체에 락을 걸었다


                    getServletContext().setAttribute("foo", "22");
                    getServletContext().setAttribute("bar", "42");

                    out.println(getServletContext().getAttribute("foo"));
                    out.println(getServletContext().getAttribute("foo"));
        }
}

컨텍스트에 락을 걸었기 떄문에 동기화 코드 블럭 안에서는(빠져나가기전까지는) 컨텍스트 속성이 다른 스레드로부터 안전하다는것을 의미한다. "안전하다"라는 말은 "ServletContext에 대한 동기화를 걸어 둔 다른 코드로부터 안전하다"를 의미하지
그렇지 않은 코드에 대해서는 안전하지 못하다

그나마 이 방법이 컨텍스트 속성을 스레드 - 안전하게 만드는 우리가 할수있는 최선이다.

세션(Session) 속성은 스레드 - 안전한가?

Http세션은 뒤에서 자세히 설명하겠지만 간단하게 설명하면

세션은 클라이언트와 대화 상태(Conversational state)를 유지하기 위하여 사용하는 객체이다.

하나의 클라이언트가 어느 정도 시간 간격으로 보내는 여러 번의 요청에도 세션은 유지된다.(하나의 클라이언트라는 말이 중요)

클라이언트 당 세션은 하나이니 어차피 어느 특정 시점에서는 한번에 하나의 요청만 들어오므로 자동적으로

세션이 스레드-안전하다고 생각할수도 있다. 하지만 클라이언트가 하나 이상의 브라우저를 열 겨우 서로 다른 브라우저로부터

온 요청이지만, 컨테이너는 동일한 세션을 사용할 것이다. 그렇게떄문에 세션 속성도 스레드 -안전하지 못하므로 보호되어야한다.

컨텍스트에 락을 걸었던것처럼 세션에도 락을걸면된다.

public void doGet(HttpServletRequest request, Http ServletResponse response)
                                                               throws IOException, ServletException){
                  response.setContentType("Text/html");
                  printWriter out = response.getWriter();

                  out.println("test context attributes<br>");
                  HttpSession session = request.getSession();
            synchronized(session){
//세션 속성을 보호하기위해 HttpSession객체에 락을 걸었다


                          session.setAttribute("foo", "22");
                          session.setAttribute("bar", "42");

                          out.println(session.getAttribute("foo"));
                          out.println(session.getAttribute("foo"));
            }
}

Request속성

단지 Request속성과 지역 변수만이 스레드 안전하다.(메소드 파라미터도 지역 변수에 포함)

이를 제외한 나머지는 멀티스레딩을 중지하지 않는 한, 멀티 스레딩 에 안전하지못하다

Request 속성은 애플리케이션의 다른 컴포넌트가 Request 또는 Request의 일부를 넘겨받기 위해 사용한다.

단순한 MVC 애플리케이션을 보면, 대부분 서블릿 컨트롤러로부터 시작해서 JSP 뷰료 끝이 난다는 것을 알 수 있다.

컨트롤러는 모델과 커뮤니케이션하여 Response를 만들기 위하여 뷰에게 데이터를 넘겨준다. 이떄 데이터를 컨텍스트나 세션 속성

넣을 필요까지 없다. 단지 이번 요청에 대해서만 사용할 데이터니깐 Request에 넣어 두는 것이 낫기 때문이다.

다른 컴퓨넌트에 Request 를 넘기는 방법은 RequestDispatcher 을 사용하면된다.

//doGet()의 일부
BeerExpert be = new BeerExpert();
ArrayList result = be.getBrands(c);

request.setAttribute("styles", result);       //모델 데이터를 request에 넣어둔다
     RequestDispatcher view = request.getRequestDispatcher("result.jsp");
     //JSP 뷰를 위한 디스패처를 리턴 받는다.
view.porward(request, response);
//JSP에게 "Request를 넘겨 받아라" 라고 말하는 것.

'공부 > Sevlets&JSP' 카테고리의 다른 글

세션(sisson) 관리  (0) 2011.06.29
RequestDispatcher  (0) 2011.06.29
Attribute(속성)  (0) 2011.06.28
ServletContextListener  (0) 2011.06.27
ServletConfig 와 ServletContext  (0) 2011.06.27