threads lock_guard example c++ multithreading c++11 boost mutex

lock_guard - ¿Es inteligente reemplazar boost:: thread y boost:: mutex con c++ 11 equivalentes?



mutex example (6)

Motivación: por lo que estoy considerando es que mi genio gerente de proyecto piensa que impulsar es otra dependencia y que es horrible porque "usted depende de eso" (traté de explicar la calidad del impulso, luego me rendí después de un tiempo :( ). Una razón más pequeña por la que me gustaría hacerlo es que me gustaría aprender las características de c ++ 11, porque las personas comenzarán a escribir código en él.

  1. ¿Hay un mapeo 1: 1 entre #include<thread> #include<mutex> y aumente los equivalentes?
  2. ¿Consideraría una buena idea reemplazar las mejoras con c ++ 11?
    cosas. Mi uso es primitivo, pero ¿hay ejemplos cuando std no ofrece lo que hace boost? O (blasfemia) viceversa?

PD: uso GCC para que los encabezados estén allí.


Con Visual Studio 2013, std::mutex parece comportarse de manera diferente que boost::mutex , lo que me causó algunos problemas (vea esta pregunta ).



Hay varias diferencias entre Boost.Thread y la biblioteca de hilos estándar de C ++ 11:

  • Boost admite la cancelación de subprocesos, C + + 11 subprocesos no
  • C ++ 11 admite std::async , pero Boost no
  • Boost tiene un boost::shared_mutex para el boost::shared_mutex de múltiples lectores / escritor único. El std::shared_timed_mutex análogo está disponible solo desde C ++ 14 ( N3891 ), mientras que std::shared_mutex está disponible solo desde C ++ 17 ( N4508 ).
  • Los tiempos de espera de C ++ 11 son diferentes a los tiempos de espera de Boost (aunque esto debería cambiar pronto, ahora se ha aceptado Boost.Chrono).
  • Algunos de los nombres son diferentes (por ejemplo, boost::unique_future vs std::future )
  • La semántica de argumento de paso de std::thread es diferente para boost::thread --- Boost usa boost::bind , que requiere argumentos para copiar. std::thread permite pasar tipos de solo movimiento como std::unique_ptr como argumentos. Debido al uso de boost::bind , la semántica de marcadores de posición como _1 en expresiones de enlace anidado también puede ser diferente.
  • Si no llama explícitamente a join() o detach() , boost::thread destructor y el operador de asignación llamarán a detach() en el objeto thread que está siendo destruido / asignado. Con un objeto C ++ 11 std::thread , esto dará como resultado una llamada a std::terminate() y abortará la aplicación.

Para aclarar el punto sobre los parámetros solo de movimiento, lo siguiente es C ++ 11 válido, y transfiere la propiedad del int del std::unique_ptr temporal al parámetro de f1 cuando se inicia el nuevo hilo. Sin embargo, si usa boost::thread , no funcionará, ya que usa boost::bind internamente, y std::unique_ptr no se puede copiar. También hay un error en la biblioteca de hilos de C ++ 11 provisto con GCC que evita que esto funcione, ya que usa std::bind en la implementación allí también.

void f1(std::unique_ptr<int>); std::thread t1(f1,std::unique_ptr<int>(new int(42)));

Si está utilizando Boost entonces probablemente pueda cambiar a C ++ 11 hilos relativamente sin problemas si su compilador lo admite (por ejemplo, las versiones recientes de GCC en Linux tienen una implementación mayoritariamente completa de la biblioteca de hilos de C ++ 11 disponible en -std=c++0x ).

Si su compilador no admite subprocesos de C ++ 11, entonces es posible que pueda obtener una implementación de terceros como Just :: Thread , pero esto sigue siendo una dependencia.


Intenté usar shared_ptr desde std en lugar de boost y encontré un error en la implementación de gcc de esta clase. Mi aplicación se estaba bloqueando debido a que destructor llamó dos veces (esta clase debería ser segura para subprocesos y no debería generar tales problemas). Después de mover a boost :: shared_ptr, todos los problemas desaparecieron. Las implementaciones actuales de C ++ 11 aún no están maduras.

Boost también tiene más funciones. Por ejemplo, el encabezado en la versión estándar no proporciona el serializador a una transmisión (es decir, cout << duration). Boost tiene muchas bibliotecas que usan sus propios equivalentes, etc., pero no cooperan con las versiones estándar.

En resumen, si ya tiene una aplicación escrita usando boost, es más seguro mantener su código como está, en lugar de esforzarse para pasar al estándar C ++ 11.


std::thread está modelado en gran medida después de boost::thread , con algunas diferencias :

  • Las semánticas de boost que no se pueden copiar y que se manejan con un solo identificador son ocultas. Pero este hilo se puede mover para permitir el retorno del hilo desde las funciones de fábrica y su colocación en contenedores.
  • Esta propuesta agrega cancelación al boost::thread , que es una complicación significativa. Este cambio tiene un gran impacto no solo en el hilo, sino también en el resto de la biblioteca de threads C ++. Se cree que este gran cambio es justificable debido al beneficio.
    • El destructor de subprocesos ahora debe llamar cancelar antes de separarse para evitar filtrar accidentalmente subprocesos secundarios cuando se cancelan subprocesos principales.
    • Ahora se requiere un miembro de separación explícito para permitir la separación sin cancelar.
  • Los conceptos de identificador de subprocesos e identidad de subprocesos se han separado en dos clases (son de la misma clase en boost::thread ). Esto es para facilitar la manipulación y el almacenamiento de la identidad del hilo.
  • Se ha agregado la capacidad de crear un id. De subproceso que se garantiza que se compara igual a ningún otro subproceso que se pueda unir ( boost::thread no tiene esto). Esto es útil para el código que quiere saber si se está ejecutando con el mismo hilo que una llamada anterior (los mutex recursivos son un ejemplo concreto).
  • Existe una "puerta trasera" para obtener el manejador de subproceso nativo para que los clientes puedan manipular subprocesos utilizando el sistema operativo subyacente, si así lo desean.

Esto es de 2007, por lo que algunos puntos ya no son válidos: boost::thread tiene ahora una función native_handle y, como comentan los comentaristas, std::thread ya no tiene cancelación.

No pude encontrar ninguna diferencia significativa entre boost::mutex y std::mutex .


Caso de la empresa

Si está escribiendo software para la empresa que necesita ejecutarse en una variedad moderada a grande de sistemas operativos y, en consecuencia, compila con una variedad de compiladores y versiones compiladoras (especialmente las relativamente antiguas) de esos sistemas operativos, mi sugerencia es mantenerse alejado de C ++ 11 en conjunto por ahora. Eso significa que no puede usar std::thread , y le recomendaría usar boost::thread .

Funda de inicio básica / técnica

Si está escribiendo para uno o dos sistemas operativos, está seguro de que solo tendrá que compilar con un compilador moderno que en su mayoría sea compatible con C ++ 11 (por ejemplo, VS2015, GCC 5.3, Xcode 7), y usted no está ya Depende de la biblioteca de impulso, entonces std::thread podría ser una buena opción.

Mi experiencia

Personalmente, soy partidario de bibliotecas reforzadas, altamente utilizadas, altamente compatibles y altamente consistentes, como el impulso frente a una alternativa muy moderna. Esto es especialmente cierto para temas complicados de programación como el enhebrado. Además, he experimentado un gran éxito con boost::thread (y boost en general) en una amplia gama de entornos, compiladores, modelos de subprocesamiento, etc. Cuando es mi elección, elijo boost.