2009-12-01 2 views
1

Naively, 나는 ThreadLocal이 값 유형에 대한 Thread의 WeakHashMap과 같은 어떤 것으로 기대했다. 그래서 ThreadLocal의 값이 실제로 saved in a map in the Thread이라는 것을 알았을 때 약간의 의아해했습니다. 그렇게 된 이유는 무엇입니까? 값이 ThreadLocal 자체에 저장되는 경우 ThreadLocal과 연결된 resource leaks이 거기에 없을 것으로 예상됩니다.java.lang.ThreadLocal이 ThreadLocal 대신에 Thread의 맵입니까?

명확한 설명 : 나는 스레드가 사망 할 때까지이있어 ThreadLocal도이 값을 통해 남아도는 지금까지 가비지 수집 될 수 있다는 이상한 문제를 방지 할 볼 수있는 나는 지금까지

public class AlternativeThreadLocal<T> { 
    private final Map<Thread, T> values = 
     Collections.synchronizedMap(new WeakHashMap<Thread, T>()); 
    public void set(T value) { values.put(Thread.currentThread(), value); } 
    public T get() { return values.get(Thread.currentThread());}  
} 

같은 것을 생각하고 있었는데 그 값이 ThreadLocal 그 자체를 어떻게 든 강하게 참조한다면. (ThreadLocal이 값을 참조하는 클래스의 정적 변수 인 경우 가장 눈에 띄는 형태 일 것입니다.) 이제 개체 나 클래스를 수집 할 수 없기 때문에 응용 프로그램 서버의 재배치시 큰 리소스 누출이 발생합니다.

답변

8

때로는 질문하는 것만으로도 깨달을 수 있습니다. :-) 이제는 스레드 안전이라는 한 가지 가능한 대답을 보았습니다. 값을 가지는 맵이 Thread 오브젝트에있는 경우, 새로운 값의 삽입은, 통상, thread 세이프 인 것입니다. 맵이 ThreadLocal에있는 경우 일반적인 동시성 문제가 발생하므로 작업 속도가 느려질 수 있습니다. (물론 당신은 동기화 대신 ReadWriteLock을 사용할 것이지만 문제는 남아 있습니다.)

4

ThreadLocal 누수 문제를 오해하고있는 것처럼 보입니다. ThreadLocal 누수는 동일한 스레드가 반복적으로 사용될 때 (예 : 스레드 풀에서 ThreadLocal 상태가 사용간에 지워지지 않을 때 발생합니다. 스레드 자체가 아닌 ThreadLocal Map을 참조하는 것이 없으므로 스레드가 파괴 될 때 ThreadLocal이 남아있는 결과는 아닙니다.

Thread-local 개체에 대한 약한 참조 맵을 사용하면 스레드가 스레드 풀에 여전히 존재하므로 ThreadLocal 누수 문제가 발생하지 않으므로 스레드 로컬 개체는 스레드를 다시 사용할 때 컬렉션에 적합하지 않으므로 수영장. 누설을 피하려면 ThreadLocal을 수동으로 지워야합니다.

답변에서 말했듯이 스레드 당 하나의 인스턴스 인 ThreadLocal Map을 사용하면 동시성 제어가 단순 해집니다. 또한 한 스레드가 다른 스레드의 로컬 객체에 액세스하는 것을 불가능하게합니다. ThreadLocal 객체가 제안한지도에서 API를 노출 한 경우는 그렇지 않을 수도 있습니다.

+0

ThreadLocal 메모리 누수의 더 위험한 형태는 값과 ThreadLocal 자체 사이의 원형에 기인합니다. 이것은 ThreadLocal을 멤버로 선언하는 클래스를 확장하는 값과 같이 미묘한 방식으로 발생합니다. – erickson

+0

실랑킹 (sylvarking)에 의해 논의 된 더 많은 문제가있는 누출을 실제로 생각하고있었습니다. API에 관해서는 현재의 API와 동일 할 수 있습니다 (내 설명 참조). 맵은 합리적인 API 디자이너에 의해 숨겨 질 것입니다. :-) –

0

몇 년 전에 Sun은 스레드 로컬의 구현을 현재 양식으로 변경했습니다. 나는 그것이 어떤 버전인지, 오래된 impl이 어떤 것인지 기억하지 못합니다.

어쨌든 각 스레드가 슬롯을 가져야하는 변수의 경우 스레드는 자연 선택 컨테이너입니다. 가능한 경우 스레드 로컬 변수를 Thread 클래스의 멤버로 직접 추가합니다.

0

MapThreadLocal 인 이유는 무엇입니까? 그것은 많은 의미를 가지지 않습니다. 그러면 ThreadLocal 내부의 객체에 대한 ThreadLocal의지도가됩니까? 그것은 그 Map 어떤 방식으로 노출되지 않는 즉, 구현 세부 사항의

  1. ; 때문에

    이 객체에 Thread의의지도의 간단한 이유는

  2. 항상 현재 스레드 (Thread.currentThread())를 알아내는 것은 쉽습니다.

또한 아이디어는, ThreadLocal을 그것이 스레드를 기반으로한다는 것이 의미가 있으므로 그것을 사용하는 각 스레드에 대해 다른 값을 저장할 수 없습니다입니까?

+0

내 설명을 참조하십시오. 나는 ThreadLocal의 멤버로서 그것을 구현하는 것이 훨씬 자연 스럽다고 생각하지만, 나의 대답에서 논의했듯이 이것은 단점을 가지고있다. –