Boa noite, Felipe! Como vai?
O synchronized
é um modificador que indica que determinado bloco de código (quando se estuda concorrência, esse bloco é chamado de seção crítica) deve ser acessado por apenas uma única thread por vez. É um dos métodos utilizados na programação em Java para garantir que os dados permaneçam consistentes em ambientes multithread.
Já os semáforos são estruturas que tbm terão como objetivo garantir que os dados permaneçam consistentes em ambientes multithread. No entanto, eles permitem funcionalidades diferentes como configurar a quantidade de threads que podem acessar a seção crítica. Fora que com os semáforos o desenvolvedor ganha mais poderes (e, portanto, mais responsabilidades), pois é ele quem define explicitamente quando uma thread entra na seção crítica e quando ela sai.
Ou seja, a escolha de um ou de outro vai depender do problema que vc estiver tentando resolver.
PARA SABER MAIS:
https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
https://docs.oracle.com/javase/10/docs/api/java/util/concurrent/Semaphore.html
Pegou a ideia? Qualquer coisa é só falar!
Grande abraço e bons estudos!