2012-03-13 19 views
18

Estoy cambiando un programa de un solo hilo en multi thread usando boost: thread library. El programa usa unordered_map como hasp_map para búsquedas. Mi pregunta es ..unordered_map thread safety

Hubo un tiempo en muchos hilos van a escribir, y en otro muchos van a leer, pero no tanto en lectura y escritura al mismo tiempo, es decir, o bien todos los hilos van a leer o todos van a escribir. ¿Será seguro y el contenedor diseñado para esto? Y si lo será, ¿será realmente concurrente y mejorará el rendimiento? ¿Debo usar algún mecanismo de bloqueo?

Leí en alguna parte que el Estándar C++ dice que el comportamiento será indefinido, pero ¿eso es todo?

ACTUALIZACIÓN: También estaba pensando en Intel concurrent_hash_map. ¿Será esa una buena opción?

+2

"pero eso es todo ... ser UB debería ser suficiente para no hacerlo. – PlasmaHH

+0

Lea esto http://stackoverflow.com/questions/1362110/is-the-c-stl-stdset-thread-safe – xanatos

+0

@PlasmaHH Si es específico de la implementación podría ser, si desea escribir su código para ese implementador. Si escribe código para Windows, la forma en que Microsoft implemente algo podría ser suficiente para usted. – xanatos

Respuesta

36

contenedores STL están diseñados para que se le garantiza a ser capaz de tener:

A. Varios subprocesos de lectura, al mismo tiempo

o

B. Una escritura hilo a la vez

Tener varios hilos escribiendo no es una de las condiciones anteriores y no está permitido. La escritura de múltiples hilos creará una carrera de datos, que es un comportamiento indefinido.

Puede usar un mutex para solucionar esto. Un shared_mutex (combinado con shared_locks) sería especialmente útil ya que ese tipo de mutex permite múltiples lectores simultáneos.

http://eel.is/c++draft/res.on.data.races#3 es la parte de la norma que garantiza la capacidad de utilizar al mismo tiempo funciones const en diferentes subprocesos. http://eel.is/c++draft/container.requirements.dataraces especifica algunas operaciones adicionales no const que son seguras en diferentes subprocesos.

+0

@ EthanSteinberg- std :: mutex? o impulsar: mutex? – questions

+0

@ preguntas Son todos iguales. Boost :: mutex podría ser un poco más fácil de usar ya que muchos más compiladores lo soportan que std :: mutex. – Lalaland

+0

@ EthanSteinberg- No necesito tener bloqueos en los lectores, ¿verdad? Porque varios hilos pueden leer al mismo tiempo. – questions

5

¿Serán seguros y el contenedor diseñado para esto?

No, los contenedores estándar no son seguros para la rosca.

¿Debo utilizar algún mecanismo de bloqueo?

Sí, lo hace. Ya que está usando boost, boost::mutex sería una buena idea; en C++ 11, hay std::mutex.

Leí en alguna parte que el estándar C++ dice que el comportamiento será indefinido, pero ¿eso es todo?

De hecho, el comportamiento no está definido. No estoy seguro de a qué te refieres con "¿eso es todo?", Ya que el comportamiento indefinido es el peor tipo posible de comportamiento, y un programa que lo exhibe es por definición incorrecto. En particular, la sincronización incorrecta de subprocesos puede provocar bloqueos aleatorios y daños en los datos, a menudo de forma muy difícil de diagnosticar, por lo que sería prudente evitarlo a toda costa.

ACTUALIZACIÓN: También estaba pensando acerca de Intel concurrent_hash_map. ¿Será esa una buena opción?

Suena bien, pero nunca lo he usado, así que no puedo ofrecer una opinión.

3

Las respuestas existentes cubrir los puntos principales:

  • debe tener una cerradura para leer o escribir en el mapa
  • se puede utilizar un bloqueo de múltiples lector/single-escritor para mejorar la concurrencia

Además, debe tener en cuenta que:

  • utilizando un-Retrie anteriormente ved iterator, o una referencia o puntero a un elemento en el mapa, cuenta como una operación de lectura o escritura

  • operaciones de escritura realizadas en otros hilos pueden invalidar punteros/referencias/iteradores en el mapa, como lo harían si se realizaron en el mismo hilo, incluso si se adquiere un bloqueo de nuevo antes de que se hizo un intento de continuar con ellos ...

1

puede utilizar concurrent_hash_map o emplear un mutex cuando accede a unordered_map. Uno de los problemas al usar Intel concurrent_hash_map es que debes incluir TBB, pero ya usas boost.thread. Estos dos componentes tienen una funcionalidad superpuesta y, por lo tanto, complican la base de tu código.

1

std :: unordered_map cumple los requisitos de Container (ref http://en.cppreference.com/w/cpp/container/unordered_map). Para la seguridad del hilo del contenedor, ver: http://en.cppreference.com/w/cpp/container#Thread_safety.

puntos importantes:

  • "diferentes elementos en el mismo recipiente se pueden modificar simultáneamente por diferentes hilos"
  • "Todos los métodos constantes se pueden llamar al mismo tiempo por diferentes hilos de rosca en el mismo contenedor Además. , las funciones miembro comienzan(), end(), rbegin(), rend(), front(), back(), data(), find(), lower_bound(), upper_bound(), equal_range(), at (), y, excepto en contenedores asociativos, operador [], se comportan como const a los efectos de seguridad de subprocesos (es decir, también pueden ser llamados concurrentemente por diferentes subprocesos en el mismo contenedor) ".