2017-01-02 2 views
2

안전이 클래스의 스레드를 확인하고 나는 이전 시험 문제에서 다음 비 스레드 안전 코드가 있습니다난 그냥 시험을 위해 공부하고

class Q3 { 
    private boolean f[] = new boolean[20]; 

    public Q3() { 
     for (int j = 0; j < 20; j++) { 
      f[j] = true; 
     } 
    } 

    public void negate(int a, int b) { 
     for(int j = a; j < b; j++) { 
      f[j] = !f[j]; 
     } 
    } 

    public void swap(int a, int b) { 
     boolean temp = f[a]; 
     f[a] = f[b]; 
     f[b] = temp; 
    } 
} 

내가 그것을 다음과 같은 조정을하여 스레드 안전 만들어를 :

class Q3 { 
    private boolean f[] = new boolean[20]; 

    public Q3() { 
     for (int j = 0; j < 20; j++) { 
      f[j] = true; 
     } 
    } 

    synchronized void negate(int a, int b) { 
     for (int j = a; j < b; j++) { 
      f[j] = !f[j]; 
     } 
    } 

    synchronized void swap(int a, int b) { 
     boolean temp = f[a]; 
     f[a] = f[b]; 
     f[b] = temp; 
    } 
} 

그러나 누군가 원래의 코드가 스레드 안전하지 않은 이유를 설명 할 수 있습니까? 나는 그렇게하지 않으면 코드를 안전하게 할 수있는 방법을 안다. 그러나 나는 여전히 코드가/스레드 안전성으로 정의되지 않았다는 것을 확신하지 못한다.

+0

'Q3' 클래스가 어떻게 사용되고 있는지 보여줄 수 있습니까? –

+0

정말 어떤 상황에서도 사용되지 않고 있습니다. 코드는 스레드의 안전성을 보장하기 위해 질문을합니다. 코드의 스레드가 아닌 스레드가 안전하지 않은 이유는 궁금합니다. 질문이지만 스레드 안전 코드인지 또는 스레드 안전하지 않은 코드인지 구분하는 방법을 알고 싶습니다. –

+0

@ JohnP.Lally 솔루션을 게시하면서 가장 최근의 질문을 삭제했습니다. 'android : minSdkVersion = "10"'은 ''이어야합니다. 귀하의 빌드가 실패해야합니다 –

답변

1

두 스레드가 동시에 각각 부정과 교환을 호출하고 모든 색인이 초기에 값이 참이라고 가정 해 보겠습니다. 이제 두 스레드가 동시에 4 번째 인덱스에서 value = true를 읽습니다. 1 번째의 thread 호출은 무효화되어, 4 번째의 요소를 무효로하는 동시에, 2 번째의 thread는 4 번째의 요소를 읽어 들여, 5 번째의 요소에 스왑합니다. 이 경우 최종 결과는 4 번째 색인 값 = false 5 번째 색인 값 = true가됩니다.

이제 우리는 실행 순서를 예측할 수 없으므로 다른 실행 시나리오가 될 수 있습니다. 스레드 1 읽기 4 번째 요소는 false가되고 스레드 2는 스레드 1이 업데이트 된 후 값을 읽으므로 false로 읽고이 값을 5 번째 요소로 바꿉니다. 따라서이 경우 최종 결과는 4 번째 인덱스 값 = true이고 5 번째 인덱스 = false 일 것입니다. 그래서 결론적으로 동기화하지 않으면 스레드 실행 순서를 예측할 수 없으며 예기치 않은 결과가 발생할 수 있습니다. 따라서 동기화 할 때이 두 메서드는 함께 호출되지 않으므로 여러 스레드가 동시에 같은 인덱스 요소를 읽고 쓸 수 없습니다.

2

이 답변은 여러 스레드가 같은 스레드에서 동작 할 수 있다고 가정한다. Q3 개체의 인스턴스입니다. 예제로 swap() 방법을 촬영 : 두 개의 스레드가 모두 호출 swap() 및 인터리브한다면

public void swap(int a, int b) { 
    boolean temp = f[a]; 
    f[a] = f[b]; 
    f[b] = temp; 
} 

다음은 일어날 수 :

Thread one: 
boolean temp = f[a]; 
f[a] = f[b]; 

Thread two: 
boolean temp = f[a]; // his temp = f[b], wrong! 

Thread one: 
f[b] = temp;   // f[b] = f[b], no swap! 

Thread two: 
f[a] = f[b]; 
f[b] = temp;   // f[a] = f[b], wrong 

이의 최종 결과는 모두 f[a]f[b] 그 후자의 값으로 끝납니다. 모두 스레드입니다. 이는 분명히 원하는 것이 아닙니다. swap() 메소드를 synchronized으로 지정하면 특정 스레드가 해당 메소드 을 원자으로 실행하게됩니다. 즉 주어진 스레드는 전체 메소드를 단독으로 완료 할 수도 있고 그렇지 않을 수도 있습니다.

+0

아, 그래, 당신이 지금 무슨 말을하는지 이해할 것 같아요, 고마워요! –

+0

@ JohnP.Lally upvote가 가능합니까? –

+0

나는 시도했으나 명성이 15 점 미만이기 때문에 나를 보내지 않을 것이다. –