http://gcc.gnu.org/onlinedocs/libstdc++/manual/shared_ptr.html을 읽고 있으며 일부 스레드 안전 문제가 여전히 명확하지 않습니다.
- 표준은 참조 카운팅이 스레드로부터 안전하게 처리되고 플랫폼 독립적임을 보장합니다.
- 비슷한 문제-표준은 하나의 스레드 (마지막 참조 보유) 만 공유 객체에서 삭제를 호출하도록 보장합니다.
- shared_ptr은 그 안에 저장된 객체에 대한 스레드 안전을 보장하지 않습니까?
편집하다:
의사 코드 :
// Thread I
shared_ptr<A> a (new A (1));
// Thread II
shared_ptr<A> b (a);
// Thread III
shared_ptr<A> c (a);
// Thread IV
shared_ptr<A> d (a);
d.reset (new A (10));
스레드 IV에서 reset ()을 호출하면 첫 번째 스레드에서 생성 된 A 클래스의 이전 인스턴스가 삭제되고 새 인스턴스로 대체됩니까? 또한 IV 스레드에서 reset ()을 호출하면 다른 스레드가 새로 생성 된 객체 만 볼 수 있습니까?
답변
다른 사람들이 지적했듯이 원래의 3 가지 질문에 대해 올바르게 파악했습니다.
하지만 편집의 마지막 부분은
스레드 IV에서 reset ()을 호출하면 첫 번째 스레드에서 생성 된 A 클래스의 이전 인스턴스가 삭제되고 새 인스턴스로 대체됩니까? 또한 IV 스레드에서 reset ()을 호출하면 다른 스레드가 새로 생성 된 객체 만 볼 수 있습니까?
부정확하다. 만 d
새로운 가리 킵니다 A(10)
하고 a
, b
그리고 c
원래의 지점으로 계속됩니다 A(1)
. 이것은 다음의 짧은 예에서 명확하게 볼 수 있습니다.
#include <memory>
#include <iostream>
using namespace std;
struct A
{
int a;
A(int a) : a(a) {}
};
int main(int argc, char **argv)
{
shared_ptr<A> a(new A(1));
shared_ptr<A> b(a), c(a), d(a);
cout << "a: " << a->a << "\tb: " << b->a
<< "\tc: " << c->a << "\td: " << d->a << endl;
d.reset(new A(10));
cout << "a: " << a->a << "\tb: " << b->a
<< "\tc: " << c->a << "\td: " << d->a << endl;
return 0;
}
(분명히, 나는 어떤 스레딩도 신경 쓰지 않았습니다. 그것은 shared_ptr::reset()
행동에 영향을 미치지 않습니다 .)
이 코드의 출력은 다음과 같습니다.
a : 1 b : 1 c : 1 d : 1
a : 1 b : 1 c : 1 d : 10
답변
-
맞습니다.
shared_ptr
s는 참조 카운트 값의 원자 적 증가 / 감소를 사용합니다. -
표준은 하나의 스레드 만 공유 객체에서 삭제 연산자를 호출하도록 보장합니다. 공유 포인터의 복사본을 삭제하는 마지막 스레드가 delete를 호출하는 스레드가 될 것임을 구체적으로 지정했는지 확실하지 않습니다 (실제로이 경우 일 가능성이 높습니다).
-
그렇지 않습니다. 저장된 객체는 여러 스레드에서 동시에 편집 할 수 있습니다.
편집 : 약간의 후속 조치, 일반적으로 공유 포인터가 작동하는 방식에 대한 아이디어를 얻으려면 http://www.boost.org/doc/libs/1_37_0/boost/shared_ptr.hppboost::shared_ptr
소스를 참조하십시오 .
답변
std::shared_ptr
스레드로부터 안전하지 않습니다.
공유 포인터는 두 개의 포인터 쌍으로, 하나는 객체에 대한 것이고 다른 하나는 제어 블록에 대한 것입니다 (참조 카운터 보유, 약한 포인터에 대한 링크 …).
std :: shared_ptr이 여러 개있을 수 있으며 참조 카운터를 변경하기 위해 제어 블록에 액세스 할 때마다 스레드로부터 안전하지만 그 std::shared_ptr
자체는 스레드로부터 안전하거나 원 자성이 아닙니다.
std::shared_ptr
다른 스레드가 사용 하는 동안 새 개체를 할당 하면 새 개체 포인터로 끝날 수 있지만 여전히 이전 개체 => CRASH의 제어 블록에 대한 포인터를 사용합니다.