1

我有一个简单的 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;
}
}
4

2 回答 2

2

您可以创建一个包装器std::map(或者将容器类型作为模板参数,因此您可以使用类似的容器,如std::unordered_mapor std::set),它具有锁定特定条目的功能。

包装类必须镜像实际std::map类中的方法,它们的实现包含对锁的检查,否则只需调用底层容器类型中的方法。

于 2013-02-28T07:17:10.550 回答
0

如果映射已经为您要修改的每个键提供了一个条目,那么您应该能够在不同线程上修改这些键的值,只要每个线程使用不同的键集且没有重叠,并且只要没有修改映射本身的结构(即不修改映射中的键集,或以其他方式调整它的大小)。

也就是说,从技术上讲,这仅适用于 C++11。在此之前,C++ 会假装线程不存在,并且在多个线程运行时根本不保证内存模型。

于 2013-02-28T07:18:25.803 回答