2009-05-04 30 views
13

¿Alguien sabe dónde puedo encontrar una implementación que envuelve un mapa STL y lo hace seguro? Cuando digo "hilo seguro" quiero decir que solo ofrece acceso en serie al mapa, un hilo a la vez. De manera óptima, este mapa debería usar solo construcciones STL y/o boost.C + + Thread-Safe Map

Respuesta

11

No cumple con los criterios que se han especificado, pero se puede echar un vistazo a los contenedores TBB. Existe el llamado concurrent_hash_map que permite que varios hilos accedan simultáneamente a los datos en el mapa. Hay algunos detalles, pero todo está bien documentado y puede darle una idea del "contenedor simultáneo". Dependiendo de sus necesidades esto podría ser totalmente inapropiado ...

+2

¿Es dependiente de esta biblioteca Intel CPU? –

1

El boost shared_mutex proporcionaría el mejor enfoque de lector múltiple/solo escritor para envolver un mapa estándar dadas sus limitaciones. No conozco ninguna implementación "preconstruida" que se case con estos dos ya que la tarea es generalmente trivial.

+4

La tarea está lejos de ser trivial, al menos para hacer de manera eficiente, por lo que no encontrará ninguna implementación. –

+0

De acuerdo, tal vez "trivial" es la palabra incorrecta. No es DIFÍCIL de hacer, al menos en el contexto específico en el que está trabajando (a menos que tenga algunos requisitos muy específicos). – Joe

1

Esto depende de la aplicación para implementar. Un mapa "seguro para subprocesos" haría que las llamadas individuales en el mapa sean seguras para la ejecución de subprocesos, pero muchas operaciones deben realizarse a prueba de subprocesos a través de llamadas. La aplicación que usa el mapa debe asociar un mutex con el mapa, y usar ese mutex para coordinar los accesos a él.

Intentar hacer contenedores seguros para subprocesos fue un error en Java, y sería un error en C++.

+7

¿Puede explicar por qué fue un error hacer contenedores seguros para la rosca? – einpoklum

3

En general, no es una buena idea que las clases de recolección proporcionen seguridad de hilo, ya que no pueden saber cómo se usan. Serás mucho más útil al implementar tus propios mecanismos de bloqueo en los constructos de nivel superior que usan las colecciones.

+8

¿Por qué no es una buena idea? ¿Puedes indicarme algunos artículos? Simplemente no entiendo por qué Java, C#/VB (.NET) y C++ tienen bibliotecas para colecciones concurrentes si son una mala idea. Las bibliotecas respectivamente son: java.util.concurrent, System.Collections.Concurrent (.NET 4.0) y Threading Building Blocks de Intel. ¿Es el argumento de que simplemente tiene un impacto en el rendimiento al usar estas bibliotecas? Sé que algunas de las colecciones siempre devuelven una instantánea "copia" para la iteración y tal, para que pueda ver cómo sería más lento. –

+1

No entiendo por qué esas bibliotecas también tienen colecciones seguras para hilos. –

+2

No está pidiendo una clase de colección segura para subprocesos. Él quiere una "construcción de nivel superior", como usted ha hablado, que "envuelve" la implementación. – Matt

0

Pruebe esta biblioteca

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

Se lleva a cabo en un enfoque basado en la moderna política de C++.

Aquí es un poco de corte desde el enlace para mostrar la idea con el caso 'vector'

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

me ocurrió esto (que estoy seguro que se puede mejorar a tomar más de dos argumentos):

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

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

Esto le permite hacer:

// 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"; 
} 

Si desea utilizar un std :: recursive_mutex y un std :: set, que también funcionaría.