Esperando hasta que se ejecuten dos bloques asíncronos antes de iniciar otro bloque

Cuando se usa GCD, queremos esperar hasta que se ejecuten y ejecuten dos bloques asíncronos antes de pasar a los siguientes pasos de ejecución. ¿Cuál es la mejor manera de hacer eso?

Intentamos lo siguiente, pero no parece funcionar:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
    // block1
});


dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
    // block2
});

// wait until both the block1 and block2 are done before start block3
// how to do that?

dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
    // block3
});