Le pipe non hanno bisogno di sincronizzazione, ognuno scrive/legge quando è pronto e il sistema operativo gestisce il buffer in mezzo, eventualmente bloccando la chiamata di lettura quando non ci sono più dati da leggere o quella in scrittura quando il buffer è pieno.

Tieni anche presente che puoi usare i socket.