답변과 비슷한 질문이 많이 있지만이 특정 사례를 아직 이해할 수 없기 때문에 질문을하기로 결정했습니다.표준 : std :: shared_ptr의 스레드 안전성
내가 가지고있는 것은 동적으로 할당 된 배열 (MyVector)에 대한 shared_ptrs의 맵입니다. 내가 원하는 것은 잠글 필요없이 제한된 동시 액세스입니다. 나는 그 자체지도는 스레드로부터 안전하지 않습니다 것을 알고,하지만 난 항상이다, 내가 확인을해야 여기에 뭘하는지 생각 :
typedef shared_ptr<MyVector<float>> MyVectorPtr;
for (int i = 0; i < numElements; i++)
{
content[i] = MyVectorPtr(new MyVector<float>(numRows));
}
:
그와 같은 단일 스레드 환경에서 맵을 채우기
초기화 후 요소에서 읽는 하나의 스레드와 shared_ptrs가 가리키는 스레드를 대체하는 스레드가 있습니다.
스레드 1 :
for(auto i=content.begin();i!=content.end();i++)
{
MyVectorPtr p(i->second);
if (p)
{
memory_use+=sizeof(int) + sizeof(float) * p->number;
}
}
스레드 2 : 내가 할 동안 독방 감금 오류 또는 두 개의 스레드 중 하나에서 두 번 무료로 하나 후
for (auto itr=content.begin();content.end()!=itr;++itr)
{
itr->second.reset(new MyVector<float>(numRows));
}
. 어떻게 든 놀랍지도 않지만 실제로는 얻지 못합니다.
이- I 추가하거나 다중 스레드 환경에서지도의 모든 항목을 제거하지 않으므로, 반복자는 항상 올바른 일을 가리켜 야 :
나는이 일 것이라고 생각하는 이유는있다 .
- 지도의 단일 요소를 동시에 변경하는 것은 조작이 원자적일 때만 괜찮다고 생각했습니다.
- 나는 shared_ptr (스레드 1에서 스레드 수를 늘리거나 감소시키는 ref 수를 늘리거나, 스레드 2에서 다시 설정)에서 수행하는 작업이 원자 적이라고 생각했습니다. SO Question
물론, 내 가정 중 하나 이상이 잘못되었거나 내가 생각하는대로하지 않습니다. 내 생각에 리셋은 실제로 쓰레드에 안전하지 않다. std :: atomic_exchange help?
나를 풀어줄 수 있습니까? 고마워요! 누군가가 시도하고자하는 경우
, 여기에 전체 코드의 예는 다음과 같습니다
#include <stdio.h>
#include <iostream>
#include <string>
#include <map>
#include <unistd.h>
#include <pthread.h>
using namespace std;
template<class T>
class MyVector
{
public:
MyVector(int length)
: number(length)
, array(new T[length])
{
}
~MyVector()
{
if (array != NULL)
{
delete[] array;
}
array = NULL;
}
int number;
private:
T* array;
};
typedef shared_ptr<MyVector<float>> MyVectorPtr;
static map<int,MyVectorPtr> content;
const int numRows = 1000;
const int numElements = 10;
//pthread_mutex_t write_lock;
double get_cache_size_in_megabyte()
{
double memory_use=0;
//BlockingLockGuard guard(write_lock);
for(auto i=content.begin();i!=content.end();i++)
{
MyVectorPtr p(i->second);
if (p)
{
memory_use+=sizeof(int) + sizeof(float) * p->number;
}
}
return memory_use/(1024.0*1024.0);
}
void* write_content(void*)
{
while(true)
{
//BlockingLockGuard guard(write_lock);
for (auto itr=content.begin();content.end()!=itr;++itr)
{
itr->second.reset(new MyVector<float>(numRows));
cout << "one new written" <<endl;
}
}
return NULL;
}
void* loop_size_checker(void*)
{
while (true)
{
cout << get_cache_size_in_megabyte() << endl;;
}
return NULL;
}
int main(int argc, const char* argv[])
{
for (int i = 0; i < numElements; i++)
{
content[i] = MyVectorPtr(new MyVector<float>(numRows));
}
pthread_attr_t attr;
pthread_attr_init(&attr) ;
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
pthread_t *grid_proc3 = new pthread_t;
pthread_create(grid_proc3, &attr, &loop_size_checker,NULL);
pthread_t *grid_proc = new pthread_t;
pthread_create(grid_proc, &attr, &write_content,(void*)NULL);
// to keep alive and avoid content being deleted
sleep(10000);
}
'MyVector'에 대한 3/5/0의 규칙 ... (그리고 왜'std :: vector'를 사용하지 않겠습니까?) – Jarod42
'if (array! = NULL)'- NULL을 검사 할 필요가 없습니다. 'delete []'를 호출 할 때. – PaulMcKenzie
'shared_ptr :: operator = (const shared_ptr & other)'다른 스레드에서'other'가 지정되면 스레드 안전하지 않습니다. 'std :: atomic>'은 아마도 덜 잠금이 아니기 때문에 자물쇠에 머물고 싶지 않다면 직접 메모리를 관리해야 할 것입니다. –
Dani