Hola,
En la solución 2 veo que llamás a mazo.sacar_carta() desde el monitor tablero. Lo cual limita un poco la concurrencia, pues mientras estás bloqueado esperando al mazo, el monitor tablero va a estar inaccesible(porque el jugador va a estar adentro, sin importar si está bloqueado en otro lado). Mi idea es llamarlo desde afuera del monitor tablero, es decir que el jugador avise que quiere jugar, saque una carta (si corresponde) y luego pueda empezar a jugar o no dependiendo de la misma. Podrías controlar que el jefe de mesa no reordene hasta que todos los jugadores que quieren sacar carta se la muestren en el tablero.
Por ejemplo:
pensar_jugada();
Tablero.iniciar_jugada(booleano); (*me tranco si el jefe está reordenando, si está esperando por jugadores retorna true*)
if (booleano) then (* si el jefe está esperando por jugadores saco una carta la muestro en el tablero *)
Mazo.sacar_carta(carta);
Tablero.mostrar_carta(carta); (*me tranco si la carta es de esperar*)
end;
(*si el jefe no estaba esperando o mi carta es de jugar*)
jugar();
Tablero.terminar_jugar();
Saludos,
Jairo.