Isso está documentado em a pthread_exit(3) manpage :
To allow other threads to continue execution, the main thread should terminate by calling
pthread_exit()rather thanexit(3).
Basicamente, quando você inicia threads, o contexto de execução atual também é um thread. Os novos segmentos têm um ciclo de vida que pode não estar relacionado ao segmento principal; então você precisa terminar sua função main com pthread_exit() , caso contrário você vai acabar chamando exit() (é o que acontece depois que você retorna de main ), e isso irá parar todos os threads do processo. p>
No final de main , você não se preocupa em fornecer um valor de retorno para qualquer outro segmento, daí o uso de NULL como argumento para pthread_exit() .