Sync/Async와 Blocking/Non-Blocking은 그저 "기준"이 다를 뿐입니다. 전자는 synchronous하냐/아니냐, 후자는 block을 하냐/안하냐에따라 명명한 것 뿐입니다.
Synchronous에는 단어 의미 자체에 함정이 있습니다. Synchronous의 사전적 정의는 "동시에 일어나는" 입니다. 따라서 오히려 여러 스레드가 동시에 수행되는 Asynchronous 프로그래밍의 개념이 synchronous라는 단어에 어울릴 것 같습니다.
프로그래밍에서 Synchronous의 의미는 "동시에 일어나는" 보다는 "같은 시간대에 일어나는"이라는 의미로 생각해야합니다. 이 부분을 유의하면서 프로그래밍에 대해 생각해봅시다.
프로그래밍에서는 스레드로 이 개념을 생각해볼 수 있습니다. 멀티스레드로 구현된 프로그램을 실행시키면, 메인 스레드가 우선 생성되어 프로그램을 실행시킵니다. 메인 스레드는 스레드를 생성시켜 task를 부여할 수 있습니다. 이때, 메인 스레드와 생성된 스레드가 어떻게 작동하느냐에 따라 Sync/Async를 나눌 수 있습니다.
메인 스레드가 스레드를 생성하고 실행시켰습니다. 이때, 메인 스레드가 생성한 스레드를 자식 스레드라 명명하겠습니다. 그리고 메인 스레드가 자식 스레드에 대해 join함수를 호출하였다고 가정해봅시다. join함수를 호출하면, 자식 스레드가 실행을 끝날 때까지 메인 스레드는 block됩니다. 자식 스레드가 실행을 마치면, 메인 스레드는 깨어나 실행을 이어갑니다. 그러므로, 메인 스레드는 자식스레드의 실행 결과를 활용할 수도 있습니다. 이러한 메커니즘은 메인 스레드와 메인 스레드가 생성한 스레드가 항상 같은 시간대에 동작하도록 해줍니다. 이러한 프로그래밍 모델을 Synchronous 프로그래밍이라고 합니다. 굳이 join을 쓰는 예시라 아니더라도, 부모 스레드와 1개 이상의 자식 스레드의 수행경과를 하나의 시간선상에 이어서 놓을 수 있을때 synchronous하다고 말할 수 있습니다.

join함수를 실행시키지 않는다면, 메인 스레드는 자식 스레드의 완료를 기다리기 위해 block되지 않습니다. 따라서, 메인 스레드와 자식 스레드는 동시에 각자의 일을 수행합니다. 이 "동시에"라는 말에 synchronous를 떠올리면 안됩니다. 앞에서 언급한 것처럼, synchronous란 같은 시간대에 일어난다는 의미이지 동시에 동작한다는 의미가 아닙니다.

이 부분은 정말 간단합니다. 스레드가 block 되느냐/안되느냐에 대한 것입니다.
메인 스레드가 자식 스레드에 대해 join함수를 호출하면, 자식 스레드가 끝날때까지 메인 스레드가 block된다고 언급했었습니다. 이 경우, block이 되므로 blocking하게 동작한다고 말할 수 있습니다.
반대로, join함수를 실행시키지 않았을 경우는 메인 스레드가 block되지 않으므로 non-blocking하게 동작한다고 말할 수 있습니다.
Blocking, non-blocking 모델은 스레드 사이의 관계 뿐만 아니라, 동시성 문제를 논할때도 사용할 수 있습니다. Critical section에 대한 race condition를 해소하기 위해,
을 사용할 수 있습니다. 전자가 blocking, 후자가 non-blocking 모델입니다.
무엇이든 장단점이 존재합니다. 따라서, 상황에 따라 적절히 활용하는 것이 필요합니다. 장단점은 여기에 남기지 않지만, 의미에서 쉽게 유추할 수 있을 것이라고 생각합니다.