2012-01-03 8 views
5

quería confirmar mi comprensión de hilos y de pasar por referencia en C++. ¿Es seguro el siguiente hilo de función?rosca con la seguridad con C++ y que pasa por referencia

QString sA = "hello"; 
QString sB = "world"; 
bool someFlag = AreStringsEqual(sA,sB); 

... 

bool AreStringsEqual(QString const &stringA, QString const &stringB) 
{ 
    if(stringA == stringB) 
    { return true; } 

    return false; 
} 

creo que es seguro para subprocesos. Me gustaría que si alguien puede confirmar mi proceso de pensamiento, o decirme que no tengo idea de lo que estoy hablando :)

  • Hay dos copias de Sa y Sb en la memoria del proceso. Un conjunto se crea en la pila de Thread1 y el segundo conjunto se crea en la pila de Thread2. Como pasamos por referencia, cada subproceso solo necesita un conjunto de sA y sB en la memoria para ejecutar la llamada de función.

  • Si hubiéramos pasado por valor, podría haber hasta cuatro copias de sA y sB en la memoria del proceso (cada hilo tiene dos juegos) en algún punto donde ambos hilos estaban controlando el procesador dentro de la llamada de función .

  • En ningún caso es la memoria compartida aquí, por lo tanto, la función es hilo de seguridad.

Lo siento si esta pregunta es muy sencilla, las discusiones han frito el cerebro :)

Pris

+0

¿Qué es QString? ¿Implementa un operador "=="? Si es así, otro subproceso podría cambiar stringA o stringB durante la ejecución del operador ==, lo que podría hacer que no sea seguro para subprocesos. – user1118321

+1

No veo los hilos en el código publicado. ¿Son 'sA',' sB' y 'someFlag' globales? – ybungalobill

Respuesta

2

Su pregunta es un poco vago en donde sA y sB son declarados. Parece que están declarados dentro de una función, en cuyo caso está en lo cierto de que cada hilo tendría su propia versión de sA y sB. Pero, en la extraña posibilidad de que se declaren a nivel mundial, este no es el caso. Si entiendo su pregunta correctamente, quiso decir que los dos fueron declarados con alcance local, por lo que su primer punto es correcto. Por la misma razón, su segundo punto también es correcto.

Su tercer punto es difícil, sin embargo. En su caso particular, no se comparte memoria, por lo que su programa es un programa "seguro para subprocesos" (no estoy seguro si esa es una buena forma de expresarlo).Sin embargo, la función AreStringsEqual es no a prueba de hilos. En algún momento en el futuro, usted (u otra persona) podría usar la función con datos que es compartida, y la función en sí misma no se protege contra este uso.

+0

Incluso si se declaran en el ámbito local, se pasan por referencia, lo que significa que las ubicaciones de memoria también son accesibles para otras funciones (y subprocesos). –

+0

@IlyaKogan: No estoy seguro de entender tu punto. Si hablas de mi primer párrafo, eso simplemente se refiere a cómo cuenta las copias de 'sA' y' sB' en todo su programa, lo cual es correcto.El tema de la seguridad del hilo se trata en mi segundo párrafo, que creo que también es correcto. En cualquier caso, el hecho de que 'AreStringsEqual' use pass-by-reference no otorga inherentemente a otros hilos o funciones acceso a' sA' y 'sB' (al menos, no en su implementación). ¿Podrías aclarar tu punto? –

+0

Si llamo 'AreStringsEqual (a, b)' y luego ejecuto otro hilo que cambia el contenido de ayb, este método será vulnerable. Por lo tanto, no es seguro para subprocesos. –

3

No hay ninguna razón por qué dos hilos no se mantendrían las referencias a las mismas cadenas.

Esta función es no thread-safe porque la instrucción if(stringA == stringB) no es atómica. Primero busca stringA de memoria, y solo entonces string B.

Quedémonos stringA == stringB == 2.

Usted obtiene stringA, luego hay un interruptor de contexto y tanto stringA como stringB cambian a 3. Luego busca stringB. Su función devolvería false (porque 2 != 3) aunque stringA era igual a stringB todo el tiempo.

0

En primer lugar, no es clara en cuanto a por qué se necesitan dos copias de la misma cadena si son siempre iguales en valor.

Quizás sea seguro para subprocesos basado en el contexto que describió, pero simplemente mirando la función en sí mismo, no es Thread Safe, ya que para cuando se ejecuta la condición if, los valores de las cadenas pueden haber cambiado.

+0

Estoy bastante seguro de que el código en la pregunta es solo para fines ilustrativos. En cualquier caso, es bastante común comparar dos cadenas, y esta no es la razón por la cual la función no es segura para subprocesos. –

1

La función no es segura para subprocesos si sA y sB se comparten entre subprocesos.

Es muy posible que durante la ejecución de la función AreStringsEqual en un hilo, otro hilo intente modificar el valor de sA o sB o ambos, entonces habría una condición de carrera.

Mientras que su función no está modificando el valor, el código fuera de su función puede.

Por lo tanto, es mejor utilizar paso por valor, ya que entonces la función tendrá copias locales en la pila que se garantiza que sea seguro para subprocesos

2

A menos QString ha especificado que operator==es hilo de seguridad, la la función es no hilo seguro. La implementación de AreStringsEqual no hace nada para proteger los datos.

Usted está poniendo la responsabilidad de la seguridad del hilo en el cliente con esta implementación. El cliente debe asegurarse de que los parámetros y los datos internos de los parámetros no se modifiquen (por ejemplo, mediante otro hilo) mientras esté en AreStringsEqual. En consecuencia, pueden encontrarse haciendo copias innecesarias. Cómo exactamente esto debe suceder está dictada por la implementación de QString. Incluso las implementaciones std::string varían drásticamente =)

Para cadenas en contextos concurrentes, generalmente se toma una copia antes de mover la cadena a un contexto concurrente. Si realmente necesita ser compartido, necesitará algo para protegerlo (como un candado). Para las colecciones primitivas (por ejemplo, std::string y std::vector), querrá evitar el bloqueo en cada acceso, ya que podría matar el rendimiento y fallar con bastante facilidad. Por lo tanto, generalmente debe copiar o bloquear si debe compartir objetos que no son explícitamente seguros para subprocesos.

Por lo tanto, la implementación de AreStringsEqual no es segura para subprocesos (nuevamente, a menos que bool QString::operator==(const QString&) const garantice que es seguro para subprocesos).

Sin embargo, el uso de AreStringsEqual:

QString sA = "hello"; 
QString sB = "world"; 
bool someFlag = AreStringsEqual(sA,sB); 

estaría bien para la mayoría de las implementaciones de cuerda, ya que los parámetros y sus datos serían local al hilo.

Cuestiones relacionadas