2013-05-09 3 views
-2

자, 알겠지만 동기화를 위해 사용하는 final static 개체를 만드는 것이 가장 좋습니다.동기화 된 비 최종 목록

그러나 객체 참조가 변경되지 않으면 동시성 문제가 발생하지 않습니다.

다음 코드가 동시성을 위반합니까?

class Foo { 
    private static ArrayList<Client> clients = null; 

    public Foo() { 
     clients = new ArrayList<>(); 
     //add stuff to list here.. 
    } 

    public void addClient(Client C) { 
     synchronized(clients) { 
      clients.add(C); 
     } 
    } 
} 

내가 고객이 최종하거나 클라이언트 ArrayList이 (게터를 통해보다 단지 다른)에 직접 노출되지 않을 경우 최종 객체를 생성해야합니까? 즉, 참조가 변경되지 않도록 클라이언트 배열에 대한 set 메소드를 제공하지 않습니다.

+1

참조가 변경되지 않으면 왜 마지막으로 만들지 않습니까? –

+1

여기에 문제가 표시되지 않지만 어쨌든 문제를 해결하지 않는 이유는 무엇입니까? – Nick

+0

C++에서 final = const로 생각 했으므로 그렇게했다면 아무 것도 추가 할 수 없습니다. 그러나 그것을 검색 한 후, 나는 그것의 동일하지 않습니다. – Brandon

답변

3

Foo new Foo()의 인스턴스를 만드는 사람은 clients 배열을 덮어 씁니다. 그것은 확실히 쓰레드에 안전하지 않다.

+0

어떻게 : 정적 배열입니까? – Brandon

+0

은 정적이어서 할당 할 수 없다는 의미는 아닙니다. 당신이 원하는 것은 그것이 최종적인 것입니다. 하지만 만약 당신이 위의 코드를 컴파일하지 않는 것보다 더 정적으로 만들면 같은 멤버에게 2 개의 할당을 할 수 없기 때문에 컴파일되지 않을 것입니다. (실제 배열보다 첫 번째 null) – Asaf

2

정말로 클라이언트를 정적으로하고 싶다면, 모든 Foos가 공유하는 클라이언트 목록이 하나있다. 그래서 모든 클라이언트의 거대한 목록을 모을 수있다. 그런 다음 한번만 초기화해야한다. .

private static ArrayList<Client> clients = new ArrayList(); 

는 그러나 나는 당신이 그 경우에, 명확성를 들어, 그것을 정적으로 선언하지 않으며, 푸 ​​당 하나 개의 클라이언트 목록을 원하는이 최종 선언 할 것으로 생각한다. (연습 자바 동시성에 설명 된대로 당신이 정말로 그것을 최종 선언해야합니다 몇 가지 이상한 코너 케이스도있다.)

+0

예 :) 모든 Foos에 대해 하나의리스트를 원했기 때문에 정적으로 만들었습니다. . 나는 당신의 것과 같이 그것을 초기화하고 그것을 최종로 만들었습니다. C++에서는 생성자 또는 초기화 목록에서만 초기화 할 수 있기 때문에 확실하지 않았습니다. 아직도 자바 배우기. 그것은 깔끔한 특징입니다. 감사! – Brandon

1

가 안전하게 변경이 같은 '고객'의 선언 스레드하려면 :

private final static List<Client> clients = new ArrayList<Client>(); 

을 사용하고 이미 '동기화'를 사용하십시오.

static 키워드의 의미를 혼동하는 경우 : 정적 키워드는 '클라이언트'의 동일한 인스턴스가 Foo의 모든 인스턴스에 대해 공유됨을 의미합니다. 정적 키워드를 제거하면 각 Foo 인스턴스의 인스턴스가 'clients'가됩니다.

최종 키워드는 단순히 clients 변수를 재 지정하지 못하게합니다.

관련 문제