2011-09-16 7 views
6

경쟁 상태를 유발하는 단위 테스트를 작성해야하므로 나중에이 문제를 해결할 수 있는지 테스트 할 수 있습니다. 문제는 경쟁 조건이 매우 드물게 발생한다는 것입니다. 내 컴퓨터에는 코어가 두 개 밖에 없기 때문일 수 있습니다.Java에서 경쟁 조건 실행

코드는 같은 것입니다 다음

class MyDateTime { 
    String getColonTime() { 
    // datetime is some kind of lazy caching variable declared somewhere(does not matter) 
    if (datetime == null) { 
     initDateTime(); //Uses lazy to initlialize variable, takes some time 
    } 
    // Colon time stores hh:mm as string 
    if (datetime.colonTime == null) { 
     StringBuilder sb = new StringBuilder(); 
     //Now do some steps to build the hh:mm string 
     //... 
     //set colon time 
     datetime.colonTime = sb.toString(); 
    } 
    return datetime.colonTime; 
    } 
} 

설명 : 우리가 게으른 초기화 원하는대로 내가 언급 한 바와 같이, ( initDateTime가 dateTime에 대한 새로운 인스턴스를 할당, 그 때문에, datetime.colonTime 나중에 널 전에). 이제 스레드 A가 메소드에 진입 한 후 스케줄러가 initDateTime()을 실행할 수 있기 직전에 스레드를 중지합니다. 스레드 B는 이제 runst getColonTime(), datetime이 여전히 null이며 초기화되어 있음을 확인합니다. datetime.colonTime은 null이므로 블록이 실행되면 두 번째이고 datetime.colonTime은 StringBuilder의 값을 가져옵니다. 스케쥴러가이 행과 return 문 사이의 스레드를 중지하고 스레드 A를 재개하면 다음과 같이됩니다. initDateTime이 호출되기 바로 전에 A가 중지되었으므로 A가 을 초기화하는 initDateTime()을 호출합니다. datetime.colonTime을 null로 다시 설정하십시오. 스레드 A는 두 번째 if 블록을 입력하지만 스케줄러는 datetime.colonTime = sb.toString()보다 먼저 A를 인터럽트합니다. 호출됩니다. 결론적으로 dateTime.colonTime은 여전히 ​​null입니다. 이제 스케줄러가 B를 다시 시작하고 메서드는 null을 반환합니다.

getColonTime()을 MyDateTime의 단일 (최종) 인스턴스에 호출하는 스레드가 많아서 경쟁 조건을 유발하려고 시도했지만 일부 드문 경우에만 실패합니다. ( JUnit을 작성하는 방법에 대한 힌트 "테스트"?

+3

우선 경쟁 조건을 유발하기 위해 디버거를 사용해 볼 수 있습니다. 나는. 스레드를 시작하고 중단 점 (예 : 사이)에서 잡아서 다른 스레드를 시작하십시오. RC가 어떻게 발생했는지 생각한 후에 (지금은 아무 것도없는 것 같습니다) 성공적인 단위 테스트를 작성할 수 있습니다. – pupssman

+0

'return datetime에 도달하는 방법을 보지 못했습니다.colonTime;'을 반환하고 null을 반환합니다. hh : mm 문자열을 작성하는 방법에 문제가 없다고 확신합니까? 어쩌면 그 코드를 질문에 추가하여 그 코드를 볼 수 있습니다. – Windle

+0

나는 그것이 일어날 수있는 몇 가지 추가 설명을 추가했다. 매우 명확하지는 않다는 것을 인정해야합니다. – user3001

답변

4

Thread Weaver을 보거나 멀티 스레드 코드를 테스트하기위한 다른 프레임 워크가있을 수 있습니다. 나는 이것을 사용하지 않았지만 Users' Guide은 정확히 이런 종류의 테스트를 위해 설계된 것처럼 보입니다.

+0

나는 이미 그것을 보았지만 그것이 얼마나 적합한 지 모른다. 그 경험, 누구? – user3001

+0

나는 thread-weaver를 시도했다. 문제가있는 곳을 아는 경우 테스트에 유용합니다. 그러나 N x N 테스트는 메소드의 라인에 대해 수행 할 수 없습니다 (토론 그룹에서 요청했습니다). – user3001

7

언급했듯이 경쟁 조건은 일관되게 재현하기가 극히 어렵습니다. 그러나 평균 법칙은 당신쪽에 있습니다. 100 번 중 하나라도 실패 할 것으로 예상되는 테스트를 작성하면 수천 번 발생하게 만들면 이전 코드에서 오류를 상당히 일관되게 잡을 수 있습니다. 따라서 TDD 원칙을 유지하면서 이전과 같은 방식으로 코드를 시작하고 충분한 시간 동안 테스트를 수행해야합니다 이전 코드와 일관되게 실패하면 새 코드로 변경하고 실패하지 않는지 확인하십시오.

+0

테스트가 실패 할 확률은 높지만 테스트가 오래 걸릴 확률이 높습니다. 단위 테스트는 빠릅니다. (그러나 나는 더 좋은 생각을 가지고 있지 않다.) –

0

나는이 게시물이 꽤 오래된 것을 알고 있지만 나는 비슷한 상황에 직면하고있다. 제가하는 일은 잠자는 상태로 경쟁 조건을 호소하는 것입니다. 귀하의 경우에는

, 나는

class MyDateTime { 
     String getColonTime() throws InterruptedException{ 
      if (datetime == null) { 
       Thread.sleep(new Random().nextInt(100); //Wait to enhance the chances that multiple threads enter here and reset colonTime. 
       initDateTime(); 
      } 
      Thread.sleep(new Random().nextInt(100); //Wait to enhance the chances that colonTime stays null for a while. 
      if (datetime.colonTime == null) { 
       StringBuilder sb = new StringBuilder(); 
       datetime.colonTime = sb.toString(); 
      } 
      Thread.sleep(new Random().nextInt(100); //Wait to favour reset of colonTime by another thread in the meantime. 
      return datetime.colonTime; 
     } 
    } 

같은 것을 할 것입니다 그러나 분명히이 매우 빠른 속도로 난장판이된다. 스케줄러에게 주어진 일부 "중단 점"에 대한 모든 경로를 탐색하도록하는 방법이 있었으면합니다.

게시물이 조금 낡았 기 때문에, Java에서 경쟁 조건을 테스트하는 좋은 방법을 찾았는지 궁금합니다. 공유 할 조언이 있습니까?

감사합니다.

+1

내가 받아 들인 대답에서 말했듯이, 스레드 짜는 사람은 훌륭한 도구 였고 나는 이제 다른 사람이 있다고 생각합니다. 예를 들어, IntelliJ는 정확하게 리콜하면 멀티 스레딩 디버깅을 지원받습니다. 또한 통계는 당신쪽에 있습니다. 테스트를 충분히 자주 반복한다면, 경쟁 조건에 한 번 치게 될 것입니다. https://github.com/junit-team/junit4/wiki/Multithreaded-code를 참조하십시오. 동시성 – user3001

관련 문제