2011-02-08 3 views
5

스레드 안전 참조 카운터를 구현하는 방법에 대해 많은 질문이 있습니다. 그리고 가장 많이 투표 된 대답은 "원자 증가/감소 사용"입니다. 좋아요, 이것은 refCounter whitout을 읽고 쓰는 다른 방법을 쓰는 좋은 방법입니다. 그러나.스레드 안전 참조 카운팅에 대한 또 다른 질문

내 코드는 다음과 같습니다

void String::Release() 
{ 
    if (0 == AtomicDecrement(&refCounter))) 
     delete buffer; 
} 

겠어요 - 나는 refCounter를 줄이고 안전하게 읽습니다. 하지만 다른 스레드가 내 refCounter를 0으로 비교하는 동안 증가 시키면 어떻게 될까요 ????

내가 틀렸어?

편집 : (예)

String* globalString = new String(); // refCount == 1 after that. 

// thread 0: 
delete globalString; 
    // This invokes String::Release(). 
    // After AtomicDecrement() counter becomes zero. 
    // Exactly after atomic decrement current thread switches to thread 1. 

// thread 1: 
String myCopy = *globalString; 
    // This invokes AddRef(); 
    // globalString is alive; 
    // internal buffer is still not deleted but refCounter is zero; 
    // We increment and switch back to thread 0 where buffer will be 
    // succefully deleted; 

은 내가 잘못 건가요?

+2

? 값 0은 문자 그대로 "no reference left"를 의미합니다. –

답변

1

당신의 예가 내게 들립니다.

그러나 여기서 문제는 원자 적 조작에 관한 것이 아니라 수동으로 개체를 삭제 한 다음 곧 삭제 될 개체를 참조하는 것입니다. 레퍼런스 카운트가 1이 아닌 8 카운트라면 어떻게 될까요?

수동으로 개체를 삭제하고 무효화하는 것을 피하고 참조 계산을 처리하기 위해 병행 성을 인식하는 스마트 포인터 구현을 사용하는 것이 좋습니다.

포인터가 refcount를 0으로 감지 할 때마다 새로운 참조를 초기화하기 위해 double-checked locking처럼 다른 스레드가 참조하지 않도록 개체를 잠글 필요가 있습니다.

+2

개체에 대한 참조가 없을 때 다른 스레드가 개체에 어떻게 액세스합니까? –

+1

@Jeremy, Anton가 질문에 예를 들어, 한 스레드가 Release() 메서드를 호출하고 AtomicDecrement 호출 바로 다음에 다른 스레드가 참조 획득을 시도하는 delete 문의 전에 refcount는 0과 같지만 두 번째 thread는 refcount == 1로 객체를 지우고 삭제 직전의 refcount를 증가시켜 참조를 얻습니다. 이것은 불가능하지는 않지만 아직 불가능한 경우입니다. – vz0

+0

사람들 감사합니다. 실제로 globalString을 스레드로부터 안전하고 내부 버퍼가 아닌 것으로 만드는 문제입니다. 그래서 vz0 제안으로 작업하기 전에 먼저 globalString을 잠 가야합니다. 추신 문자열은 단지 예일뿐입니다. 실제 코드에는 좀 더 복잡한 종속성이 있습니다. –

2

주의하십시오!

더 큰 무언가의 수명주기를 관리하는 참조 카운터와 같은 변수를 보호하는 것만으로는 충분하지 않습니다. 귀하의 경우에는 내가 아주 나쁜 끝 귀하의 질문에 같은 코드를 본 적이

...

누군가가 당신 비교 후 카운터를 증가 할 수 있지만, 일부 스레드가 카운터를 얻을 수뿐만 아니라 값 1, 당신은 감소하고, 버퍼와 다른 스레드를 사용 삭제 메모리 ... CRASH 삭제

my2c는 개체에 대한 참조를 가지고 있지 않은 경우 다른 스레드가 카운터를 증가 수있는 방법