2013-02-28 73 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

順便說一句,在*句子標誌之前放置空格*是不好的做法。就這樣你知道將來的機器着作。 – 2013-02-28 09:46:02

+0

@ChristianRau我會照顧的 – 2013-03-01 07:45:37

回答

2

你可以創建一個圍繞std::map的包裝(或者說具有容器類型作爲模板參數,所以你可以使用類似容器,如std::unordered_mapstd::set),具有功能來鎖定特定條目。

包裝類必須鏡像實際的std::map類中的方法,它們的實現包含對鎖的檢查,否則只是調用底層容器類型中的方法。

+0

當然,包含鎖的並行結構也必須被鎖定。你最好鎖定原始地圖。 – 2013-02-28 07:26:09

+0

@MArk是的,這是目前的實施。然而,由於資源緊縮線程堆積爲地圖的訪問。因此我們想要鎖定宏觀層次的條目。 – 2013-02-28 07:33:15

+0

@sameerkarjatkar我在說的是,這個答案不起作用。無論您使用什麼結構來鎖定特定條目,本身都需要被鎖定。你會遇到同樣的問題,只有一個層面的間接性更深。 – 2013-02-28 07:36:24

0

如果地圖中已經有每個要修改的密鑰的條目,那麼只要每個線程使用不同的密鑰組並且沒有重疊,就應該可以修改這些密鑰在不同線程上的值,,只要沒有任何修改地圖結構本身(即不修改地圖中的一組鍵,或調整它的大小)。

這就是說,從技術上講,這隻適用於C++ 11。在此之前,當多線程運行時,C++假裝的線程不存在,並且完全不保證內存模型。

+0

如果線程在地圖中添加條目,它會干擾操作。我認爲排序/調整大小總是發生在鍵上。由於我鎖定了這個值,因此密鑰應該可以在地圖中移動 – 2013-02-28 07:27:41

+0

@sameerkarjatkar:如果地圖的結構沒有改變,那麼訪問不同線程上的值應該是安全的,只要兩個線程不要不會以相同的價值操作。 – 2013-02-28 07:38:01

+0

所以你打算說在地圖上不應該有任何增加或刪除? – 2013-02-28 07:44:36