2013-08-19 2 views
2

클래스 [X] (및 해당 오브젝트 [xObject])가 있고 정수 2 개 [A]와 [B]가 있다고 가정하십시오. 하나는 [A]를 수정하고 다른 하나는 [B]를 수정하는 두 개의 스레드가 있습니다. 두 스레드가 [xObject]의 값을 변경하기 때문에 서로 다른 메모리 위치 (실제로)가 있으므로 [xObject] 또는 [A]와 [B]에 대한 액세스를 동기화해야합니까? 그리고 어디에서이 FALL 끝나는 것처럼, 내가 배열의 두 개의 다른 위치에 동시에 액세스해야합니까 또는 arrayList 안에?오브젝트 내부에서 동기화, 오브젝트 또는 데이터가 정확히 필요합니까?

답변

1

두 개의 독립적 인 int 속성이있는 경우 전혀 동기화 할 필요가 없습니다. 동기화하는 유일한 이유는 두 개 이상의 메모리 위치가 관련되어있을 때 일관성을 유지하기 위해서입니다. 독립적 인 위치가있는 경우 volatile은 변경 사항에 대한 스레드 간 가시성을 보장하기에 충분합니다.

예를 들어, int 속성이 독립적이지 않은 경우 동기화해야합니다. 하나의 속성이 현재 값을 나타내고 다른 속성이 최대 값을 나타냅니다. max보다 큰 현재 값을 설정하면 예외가 발생합니다. 현재 값보다 큰 최대 값을 설정하면 현재 값이 새로운 최대 값으로 변경됩니다. 배열과 모음에 대한

public class Test { 
    int current = 10; 
    int max = 100; 
    public synchronized int getMax() { return max; } 
    public synchronized int getCurrent() { return max; } 
    public synchronized void setCurrent(int c) { 
     if (c > max) throw new IllegalStateException(); 
     current = c; 
    } 
    public synchronized void setMax(int m) { 
     max = m; 
     if (current > m) current = m; 
    } 
} 

결정은 더 복잡하다 : 당신 액세스 배열 요소지만, 배열 자체가 고정 된 상태를 유지하고, 배열 요소가 독립적 인 경우에, 당신은 동기화를 건너 뛸 수 있습니다. 그러나 요소가 독립적이지 않거나 컬렉션이 더 복잡한 경우 (예 : 배열 목록 또는 해시 테이블) 동기화 작업이 필요합니다. 컬렉션 작업이 컬렉션을 구조적으로 변경하여 일관성을 잃을 수 있기 때문입니다.

1

배열에 대해 무슨 뜻인지 확실하지 않지만 두 개의 서로 다른 값을 변경하고 다른 스레드에서 값을 읽지 않으면 동기화 할 필요가 없습니다. 당신이 클래스 X.

또는 사용에 같은 휘발성하지 않는 한 당신이 스레드 1 변수 xObject.a의 값을 변경하고 실 2 3 다음 오래된 얻을 수있는 몇 가지 다른 스레드를 읽고 있다면

읽기 java.util.concurrent 패키지의 동기화 유틸리티 중 하나. 구글 주위에 또는 stackoverflow 예를 들어 검색 할 수 있습니다.

0

클라이언트가 볼 수없는 중간 상태에 따라 다릅니다. 객체에 허용되지 않은 (A)의 조합 B가있는 경우

는 예를 들어, 당신은 모두가 액세스를 통해 동기화해야합니다 :

class Person { 
    private final Object _lock = new Object(); // for synchronization 

    private int _age; 
    private boolean _married; 

    public void setAge(int age) { 
    if (age <= 0) throw new IllegalArgumentException(); 

    synchronized(_lock) { 
     // age < 18 implies !married 
     _age = age; 
     if (age < 18) married = false; 
    } 
    } 
} 

당신이 작업을 수행 할 수 있습니다 경우에도 A와 B 서로 독립적 인 :

class ComplexNumber { 
    private final Object _lockRe = new Object(); 
    private final Object _lockIm = new Object(); 
    private int _re, _im; 

    ... 

    public void setValue(int re, int im) { 
    synchronized(_lockRe) { _re = re; } 
    synchronized(_lockIm) { _im = im; } 
    } 
} 

당신이 다음

ComplexNumber c = new ComplexNumber(0, 0); 
c.setValue(1, 2); 

일한다면 read는 설정되지 않은 (1,0)을 볼 수 있습니다. 이것은 응용 프로그램에 따라 허용 될 수도 있고 허용되지 않을 수도 있습니다.

1

클래스가 멀티 스레드 환경에서 사용되는 경우 getter 또는 공용 액세스를 사용하여 사용 가능한 모든 데이터를 잠그는 것이 좋습니다.

그런 식으로 특정 규칙 ("B에 액세스하는 경우 A를 수정해서는 안 됨)"을 알거나 고려하기 위해 사용자 (클래스를 API로 사용하는 코드)를 강요하지 않습니다.어떤 데이터 항목을 동기화해야하는지에 대해 신경 쓰지 않고 즉시 사용할 수있는 방법을 사용할 수 있습니다. 또한 적은 설명서;)