2013-02-28 2 views
1

У меня есть простая std :: map с ключом. Я хочу, чтобы эта карта была потокобезопасной. Я не хочу блокировать всю карту. Поскольку мои потоки будут работать (обновлять, удалять) только по значениям для определенного ключа на карте, я не хочу блокировать всю карту. Я хочу, чтобы другие потоки могли работать на карте, конечно, не на заблокированном значении.Можно ли заблокировать значение в std :: map для ключа?

Было бы целесообразным или логически правильным блокировать только значение для определенного ключа? Или я должен думать о другой структуре данных?

Обновление: Я просто попробовал пример, где у меня есть параллельные потоки, обновляющие и вставляющие на одну и ту же карту.

#include "stdafx.h" 
#include "stdafx.h" 
#include <iostream> 
#include <map> 
#include <process.h> 
#include <windows.h> 
using namespace std; 
CRITICAL_SECTION CriticalSection; 


struct newEntry 
{ 
    int key; 
    char value; 
}; 


std::map<int,char> mapIntChar; 

unsigned __stdcall UpdateThreadFunc(void* pArguments) 
{ 

    char *ptr = (char *) pArguments; 
    EnterCriticalSection(&CriticalSection); 
    *ptr = 'Z'; 
    LeaveCriticalSection(&CriticalSection); 
    _endthreadex(0); 
    return 0; 
} 

unsigned __stdcall InsertThreadFunc(void* pArguments) 
{ 
struct newEntry *ptr = (struct newEntry *) pArguments; 
mapIntChar[ptr->key] = ptr->value; 
    _endthreadex(0); 
    return 0; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    std::map<int,char>::iterator it1; 
    unsigned threadID; 
    if (!InitializeCriticalSectionAndSpinCount(&CriticalSection, 
    0x00000400)) 
    return 0; 
    mapIntChar[0] = 'A'; 
    mapIntChar[1] = 'B'; 
    mapIntChar[2] = 'C'; 
    mapIntChar[3] = 'D'; 

    HANDLE hThread; 
    int nCount = 0; 
    struct newEntry *newIns; 
    while (nCount < 1004) 
{ 
     it1 = mapIntChar.begin(); 
    char *ptr = &(it1->second); 
     hThread = (HANDLE)_beginthreadex(NULL, 0, &UpdateThreadFunc, ptr, 0, &threadID); 

     newIns = new newEntry; 
     newIns->key = rand() % 1000; 
     newIns->value = 'K'; 
    hThread = (HANDLE)_beginthreadex(NULL, 0, &InsertThreadFunc, newIns, 0, &threadID); 
    nCount++; 
     delete newIns; 
} 
} 
+0

Кстати, помещение пробелов * перед фразами предложения является плохой практикой. Просто чтобы вы знали о будущих машинных работах. –

+0

@ChristianRau Я позабочусь –

ответ

2

Вы можете создать оболочку вокруг std::map (или, скорее, имеет тип контейнера в качестве параметра шаблона, так что вы можете использовать аналогичные контейнеры, как std::unordered_map или std::set), которые имеют функциональные возможности для блокировки определенных записей.

Класс оболочки должен отражать методы в действительном классе std::map с их реализациями, содержащими проверки блокировок, но в противном случае просто вызвать метод в базовом типе контейнера.

+0

Конечно, параллельная структура, содержащая замки, также должна быть заблокирована. Вам лучше просто заблокировать исходную карту. –

+0

@MArk Да, это то, что это текущая реализация. Однако из-за нехватки ресурсов поток ресурсов для доступа к карте. Следовательно, мы хотим заблокировать записи на макроуровне. –

+0

@sameerkarjatkar, что я говорю, заключается в том, что этот ответ не работает. Любая структура, которую вы используете для блокировки определенных записей, сама по себе должна быть заблокирована. У вас будет такая же проблема, только один уровень косвенности глубже. –

0

Если на карте уже есть запись для каждой клавиши, которую вы хотите изменить, вы должны иметь возможность изменять значения этих клавиш для разных потоков, если каждый поток использует другой набор ключей без перекрытия, и, пока ничто не изменяет структуру самой карты (т. е. не изменяет набор ключей на карте или иным образом изменяет ее размеры).

Тем не менее, технически это справедливо только для C++ 11. До этого C++ притворялись нитями и не предоставляли никаких гарантий относительно модели памяти при запуске нескольких потоков.

+0

Если поток добавляет запись на карту, это нарушит работу. Я думал, что сортировка/изменение размеров всегда происходит на клавише. Поскольку я блокирую значение, ключ должен иметь возможность перемещаться по карте. –

+0

@sameerkarjatkar: Если структура карты не изменяется, то доступ к значениям на разных потоках должен быть безопасным, если два потока не будут t работают с одинаковым значением. –

+0

, так что вы хотели сказать, что на карте не должно быть никаких добавлений или удалений? –

Смежные вопросы