2010-05-04 6 views
2

doSomething()이라는 메소드가 있고 다중 스레드 응용 프로그램에서이 메소드를 사용하려고한다고 가정합니다 (각 서블릿은 HttpServlet에서 상속 받음). 가능한지 궁금합니다. 경쟁 조건은 다음과 같은 경우에 발생합니다jsp/servlets 응용 프로그램에서 Java 메소드 및 경쟁 조건

  1. doSomething()하지 staic 방법이며 데이터베이스에 값을 기록합니다.
  2. doSomething()정적 방법이지만 값을 데이터베이스에 씁니다.

내 응용 프로그램의 많은 방법으로 인해 경쟁 조건이 발생하거나 읽기/쓰기가 더렵혀 질 수 있습니다. 예를 들어, 나는 설문 조사 시스템을 가지고 있고, 각각의 투표 조작, 특정 방법은 다음과 같은 것을 조사하기위한 단일 셀의 값을 변경합니다 :

[poll_id |    poll_data  ] 
[1  | {choice_1 : 10, choice_2 : 20}] 

는 JSP/서블릿의 응용 프로그램은 그 자체로 이러한 문제를 해결할 수 , 아니면 나 혼자서 모든 것을 해결해야합니까?

감사합니다 .. 당신의 문제에 대한 최선의 해결책은 "동기화"같은 것을 사용하는 것입니다

답변

4

doSomething()이 구현되는 방식과 실제로 수행되는 방식에 따라 다릅니다. 데이터베이스에 쓰는 것은 이 아닌 threadsafe 인 JDBC 연결을 사용한다고 가정합니다. 선호하는 방법은 ThreadLocal JDBC 연결을 작성하는 것입니다.

두 번째 경우는 메소드에서 진행중인 작업에 따라 다릅니다. 공유, 변경 가능 상태에 액세스하지 않으면 문제가 발생하지 않습니다. 그렇다면 적절하게 잠글 필요가 있습니다. 이러한 변수에 대한 모든 다른 액세스에는 잠금을 추가해야 할 수 있습니다.

(단지 synchronized 이러한 방법을 표시하는 동시성 버그를 수정하지 않도록주의하십시오. doSomething() 공유 객체에 값을 증가하면, 모든 i++ 이후 synchronized가 원자 작동하지 될 그 변수 필요에 액세스합니다. 경우 AtomicInteger.incrementAndGet()을 사용할 수 있습니다.)

+0

감사합니다. 마이크. 예, 저는 JDBC를 사용합니다. ThreadLocal에 대해서도 읽어 볼 것입니다. 다시 한번 감사드립니다. – Abdullah

+1

서블릿 API 및 기타 JEE API는이 작업을 간소화합니다. 서블릿 메소드의 지역 변수는 효과적으로 스레드 로컬 (서비스 요청 지속 기간 동안)입니다. 응용 프로그램 서버의 JDBC 연결 풀링은 각 스레드에게 자체 연결을 제공합니다. 대부분의 어려움은 서로 다른 스레드가 경쟁하는 경우 발생합니다.이 경우에는 데이터베이스 자체에서 발생합니다. Affe가 말했듯이 이것이 실제 디자인 작업이 시작되는 곳입니다. – djna

0

나는 것은 키워드 및 통지/기다려!

+0

서블릿에서이 appraoch는 거의 최상의 솔루션이 아닙니다. – djna

3

서블릿 API는 당연히 병행 성을 문제가되지 않습니다.

데이터베이스에 쓰는 경우 지속성 계층의 동시성 전략에 따라 다릅니다. 비관적 잠금, 낙관적 잠금, 최후 승. '데이터베이스에 쓸 때'어떻게 처리 할 것인지 결정해야 할 때가 있습니다. 당신은 무엇입니까 은 동시에 두 사람이 버튼을 클릭 할 때 일어나는을 원하십니까?

doSomething static은 문제에 너무 많은 영향을 미치지 않습니다. 거기에서 일어나는 일은 관련 부분입니다. 정적 변수를 수정하고 있습니까? 그렇다면 경쟁 조건이있을 수 있습니다.

2

서블릿 API는 동시성 문제를 없애기 위해 아무 것도하지 않습니다. 기본적으로 서블릿에서 synchronized 키워드를 사용하는 것은 좋지 않습니다. 왜냐하면 기본적으로 한 번에 하나씩 스레드를 처리해야하고 여러 사용자에게 신속하게 응답 할 수있는 능력이 없어지기 때문입니다.

Spring 또는 EJB3을 사용하는 경우 스레드 로컬 데이터베이스 연결과 트랜잭션 지정 기능을 제공합니다. 분명히 그 중 하나를 체크 아웃해야합니다.

2

사례 1의 경우, 서블릿은 데이터베이스에 액세스하는 일부 코드를 사용합니다. 데이터베이스에는 사용자가 사용해야하는 잠금 메커니즘이 있습니다. 이것에 대한 두 가지 중요한 이유가 있습니다. 데이터베이스 자체는 데이터를 읽고 쓰는 다른 응용 프로그램에서 사용될 수 있습니다. 앱이 자체적으로 경쟁하는 것만으로는 충분하지 않습니다. 그리고 : 자신의 응용 프로그램은 코드의 여러 복사본이 별도의 컴퓨터에서 실행되는 확장되고 클러스터 된 웹 컨테이너에 배포 될 수 있습니다.

따라서 데이터베이스의 잠금을 처리하는 데 많은 표준 패턴이 있으므로 비관적 및 낙관적 잠금을 읽어야 할 수 있습니다. 당신은 개념, 자바 동기화가 변수 방법 범위에 제공 사용하지 않고 서블릿 코드를 작성할 수 있도록

서블릿 API와 JBC 연결 풀링은 그래서 유일한

Start transaction (perhaps implicit, perhaps on entry to an ejb) 
    Get connection to DB (Gets you a connection from pool, associated with your tran) 
    read/write/update code 
    Close connection (actually keeps it for your thread until your transaction commits) 
    Commit (again maybe implictly) 

가 당신에게 도움이 보증을 제공합니다 진짜 문제는 DB의 모든 논쟁을 다루는 것입니다. 위의 모든 것들은 요즘 JPA와 같은 것들을 사용하여 좀 더 정중하게 수행되는 경향이 있지만, 어떤 일이 벌어지고 있는지에 대해서는 거의 다루지 않습니다.

사례 2 : 정적 방법입니다. 이것은 아마도 모든 것을 메모리 구조로 유지한다는 것을 의미 할 것입니다. (일종의 원격 호출을 금지하는) 단일 JVM을 고수하고 자신 만의 잠금을 관리합니다. 귀하의 JVM이나 기계가 추락하면 데이터를 잃어버린 것 같아요. 데이터에 관심이 있다면 DB를 사용하는 것이 좋습니다.

또는 완전히 다른 접근 방법은 어떨까요? 서블릿은 영구 JMS 대기열에 메시지를 작성하여 "투표"를 기록합니다. 다른 프로세스가 대기열에서 투표를 선택하여 추가합니다. 이런 식으로 유권자에게 즉각적인 피드백을주지는 않겠지 만, 사용자의 경험을 실제 시나리오 (유사한 시나리오에서)와 매우 복잡한 처리로 분리합니다.

관련 문제