1. Me llama la atención que todos los valores que mencionas sean menores que 9 ¿Es imposible que exista un resultado mayor que 9? Si fuera posible, para descartar errores, podrías hacer alguna prueba donde se llegue a uno mayor.
2. Sin conocer los detalles, apostaría a que el problema es de tipo aritmético, y que no debe tener nada que ver con los threads sino con los cálculos que debes estar haciendo con ellos.
Ahora que sabemos que la secuencia:
Código:
random_device rd;
mt19937 generator(rd());
en algunos compiladores genera siempre la misma serie y en otros series distintas, yo haría pruebas generando siempre series iguales para comparar los resultados con distinto número de threads.
Por ejemplo, ejecutar el programa para 1, 2, 7, 8, 10, 20, 50, 500 y 1000 threads, para ver si hay alguna regularidad en los resultados. Lo que resulte de esa prueba seguramente será muy significativo.
El procesamiento que describes no es paralelo, es concurrente. Si fuera paralelo no tendrías esos errores.
3. Lo que te decía sobre los locks era sobre la forma en que los usas, no a que si son mejores o peores que async. Hay varias maneras de controlar el acceso a datos compartidos entre threads, y no creo que haya recetas del tipo "este es mejor que aquél"; seguramente depende de cada caso en particular y de cómo puede uno plantear su solución.