2013-02-12 1 views
2

this page의 저자는 아래의 두 번째 코드 예는 동기화 문제가 있지만 코드는 100 번에서 약 99 번 작동한다고 언급합니다.이 페이지의 두 프로그램에서 작동상의 차이점을 볼 수 없습니다.다음과 같은 동기화 문제는 어떤 동기화 문제로 발생합니까?


이전 두 결합 다소 일반적인 솔루션은 다음에, 로컬 변수로 필드 값을 복사하여 로컬 변수를 변경하는 것이다. 메서드 내에서 필드는 변경되지 않습니다. 예를 들어,

public class Counter { 

    int count = 0; 

    public void count() { 
    int count = this.count; 
    int limit = count + 100; 
    while (count++ != limit) System.out.println(count); 
    } 

} 

참고 로컬 변수 카운트 필드 카운트 그림자 방법 및 키워드 그림자 외부 필드 수를 참조하는 데 사용되는 방법.

이 트릭은 변경된 변수를 메소드가 완료 될 때 필드에 다시 저장할 필요가없는 경우에 주로 유용합니다. 다음은 상태를 저장하지만 여전히 덜 분명한 동기화 문제의 영향을받습니다. 이 여기에 버그가 소스 코드에 자리하지 않는 경우 아래 핀 매우 열심히하는 (100)에서 99 시간을 작동하기 때문에

사실
public class Counter { 

    private int count = 0; 

    public void count() { 
    int count = this.count; 
    int limit = count + 100; 
    while (count++ != limit) System.out.println(count); 
    this.count = count; 
    } 

} 

, 이것은 아마도 원래의 예보다 더 나쁘다 .

답변

2

this.count의 수정 사항이 원자 적이지 않다는 사실에 문제가 있습니다.

두 스레드가이 함수를 호출하고 있고 this.count이 현재 0으로 설정되어 있다고 가정 해 보겠습니다. 로컬 count

스레드 1로드 0하고는 101로 증가하기 시작 (100하지 앞서 한계에 도달 한 후에는 count++ != limitcount 번 더 증가 생각 때문에). 한편

는, 스레드 2는오고 this.count 그래서 그것을 잡고 101에 증가 시작 여전히 세트 0이다.

은 어떤 시점에서, 그들은 다음 두 라인 this.count = count에 도달 (및 순서는 중요하지 않습니다) 그리고 그들은 모두이 마지막에 설정되어 있어야 무엇 (101)

this.count 설정 202 (나는 생각한다 - 확실히 어딘가에 200 주위에 있어야한다).

코드의 첫 번째 비트가 유효 한 이유는 실제로 this.count 값을 변경하려고 시도하지 않아서 경쟁 조건이 불가능하기 때문입니다.

+0

답변 해 주셔서 감사합니다. 이것이 저자가 의미하는 문제라면 대부분의 시간 이후로 대부분의 시간에 발생해야하며 두 번째 스레드는 첫 번째 스레드가 완료되기 전에 시작해야합니다. 그러나 저자는 프로그램이 100 회에서 99 회 작동한다고 말합니다. 따라서 프로그램 끝에 this.count의 의도 된 값이 200인지 확실하지 않습니다. –

+0

"두 번째 스레드가 첫 번째 스레드가 시작되기 전에 시작됩니다"는 테스트되지 않은 어설 션입니다. 사실, 다른 실행 스레드를 생성하는 것이 100 반복 루프보다 빠르다면 놀랄 것입니다. 나는 테스트를 위해 그것을 실행하는 것이 좋습니다.물론 저자의 99 % 성공률에 대한 주장은 과장이 될 수도 있습니다 .-) – paxdiablo

+0

@BM : 나는이 코드에서 다른 문제를 발견 할 수 없었습니다. 특히 다음 페이지에서 저자가 제안한 전체 메소드에서 od'synchronized' 키워드를 사용하여 해당 문제에 대한 가능한 해결책 중 하나를 선택하십시오. – Crozin