2009-05-04 10 views
13

Weiß jemand, wo ich eine Implementierung finden kann, die eine STL-Map umschließt und sie threadsicher macht? Wenn ich "thread safe" sage, meine ich, dass es nur einen seriellen Zugriff auf die Karte bietet, jeweils einen Thread. Im Idealfall sollte diese Map nur STL- und/oder Boost-Konstrukte verwenden.C++ - Thread-sichere Karte

Antwort

11

Hat die Kriterien nicht erfüllen, die Sie festgelegt haben, aber man konnte einen Blick auf die TBB Behälter haben. Es gibt so genannte concurrent_hash_map, die mehreren Threads erlaubt, gleichzeitig auf die Daten in der Karte zuzugreifen. Es gibt einige Details, aber alles ist gut dokumentiert und kann Ihnen eine Vorstellung vom "Concurrent Container" geben. Je nach Bedarf kann dies völlig ungeeignet ...

+2

Ist diese Bibliothek Intel CPU abhängig? –

1

Der Boost shared_mutex würde den besten Multiple-Reader/Single-Writer-Ansatz zum Einbinden einer Standard-Map unter Berücksichtigung Ihrer Einschränkungen bieten. Ich kenne keine "vorgefertigten" Implementierungen, die diese beiden verbinden, da die Aufgabe im Allgemeinen trivial ist.

+4

Die Aufgabe ist alles andere als trivial, zumindest effizient, weshalb Sie keine Implementierungen finden. –

+0

Okay, vielleicht ist "trivial" das falsche Wort. Es ist nicht schwer zu tun, zumindest in dem spezifischen Kontext, an dem Sie arbeiten (es sei denn, Sie haben einige sehr spezifische Anforderungen). – Joe

1

Dies ist die Anwendung zu implementieren. Eine "thread-safe" Karte würde einzelne Anrufe in die Karte threadsicher machen, aber viele Operationen müssen thread-sicher gemacht werden über Anrufe. Die Anwendung, die die Zuordnung verwendet, sollte der Karte einen Mutex zuordnen und diesen Mutex verwenden, um Zugriffe darauf zu koordinieren.

Der Versuch, thread-sichere Container zu erstellen, war ein Fehler in Java, und es wäre ein Fehler in C++.

+7

Können Sie bitte erklären, warum die Herstellung von fadensicheren Behältern ein Fehler war? – einpoklum

3

Es ist in der Regel keine gute Idee, wenn Sammlungsklassen Thread-Sicherheit bieten, weil sie nicht wissen können, wie sie verwendet werden. Sie werden viel besser gedient sein, indem Sie Ihre eigenen Sperrmechanismen in den höheren Konstrukten, die die Sammlungen verwenden, implementieren.

+8

Warum ist es keine gute Idee? Kannst du mich auf Artikel aufmerksam machen? Ich verstehe einfach nicht, warum Java, C#/VB (.NET) und C++ alle Bibliotheken für gleichzeitige Sammlungen haben, wenn sie eine schlechte Idee sind. Die Bibliotheken sind: java.util.concurrent, System.Collections.Concurrent (.NET 4.0) und die Threading-Bausteine ​​von Intel. Ist das Argument, dass Sie einfach einen Leistungseinbruch durch die Verwendung dieser Bibliotheken nehmen? Ich weiß, dass einige der Sammlungen immer einen Schnappschuss "Kopie" für die Iteration und so zurückgeben, damit ich sehen kann, wie das langsamer wäre. –

+1

Ich verstehe nicht, warum diese Bibliotheken auch Thread-sichere Sammlungen haben. –

+2

Er fragt nicht nach einer Thread-sicheren Sammelklasse. Er will ein "Konstrukt auf höherer Ebene", wie du schon sagtest, das die Implementierung "umschließt". – Matt

0

Versuchen Sie, diese Bibliothek

http://www.codeproject.com/KB/threads/lwsync.aspx

Es ist in einem modernen C++ richtlinienbasierte Ansatz umgesetzt wird.

Hier ist etwas, geschnitten aus dem Link, um die Idee mit dem ‚Vektor‘ Fall zu zeigen

typedef lwsync::critical_resource<std::vector<int> > sync_vector_t; 
sync_vector_t vec; 

// some thread: 
{ 
    // Critical resource can be naturally used with STL containers. 
    sync_vector_t::const_accessor vec_access = vec.const_access(); 
    for(std::vector<int>::const_iterator where = vec_access->begin(); 
     where != vec_access->end(); 
     ++where; 
     ) 
    std::cout << *where << std::endl; 
} 

sync_vector_t::accessor some_vector_action() 
{ 
    sync_vector_t::accessor vec_access = vec.access(); 
    vec_access->push_back(10); 
    return vec_access; 
    // Access is escalated from within a some_vector_action() scope 
    // So that one can make some other action with vector before it becomes 
    // unlocked. 
} 

{ 
    sync_vector_t::accessor vec_access = some_vector_action(); 
    vec_access->push_back(20); 
    // Elements 10 and 20 will be placed in vector sequentially. 
    // Any other action with vector cannot be processed between those two 
    // push_back's. 
} 
0

ich kam mit dieser (was ich sicher bin, kann verbessert werden, um mehr als zwei Argumente zu nehmen):

template<class T1, class T2> 
class combine : public T1, public T2 
{ 
public: 

    /// We always need a virtual destructor. 
    virtual ~combine() { } 
}; 

auf diese Weise können Sie tun:

// Combine an std::mutex and std::map<std::string, std::string> into 
// a single instance. 
SCA::combine<std::mutex, std::map<std::string, std::string>> lockableMap; 

// Lock the map within scope to modify the map in a thread-safe way. 
{ 
    // Lock the map. 
    std::lock_guard<std::mutex> locked(lockableMap); 

    // Modify the map. 
    lockableMap["Person 1"] = "Jack"; 
    lockableMap["Person 2"] = "Jill"; 
} 

Wenn Sie eine std :: recursive_mutex verwenden und ein std :: set, das würde auch funktionieren.