Chiarissimo ora. La questione da comprendere è questa. Se nel try invochi banalmente i 3 metodi in sequenza e basta, all'interno di un singolo thread la sequenza è ovviamente garantita. Ma siccome ci sono 2 thread, la esecuzione dei metodi può essere intercalata tra i due thread in qualunque dei modi possibili per la sequenza.
Vuol dire che NON è affatto detto che ottieni :-):-) ma potresti anche ottenere ::--)) o ::-)-) o qualunque altra sequenza lecita. (chiaramente dopo ) c'è il newline, gli esempi li ho scritti di fila per semplicità)
Quello che serve è fare in modo che l'insieme delle 3 operazioni sia "atomico" e questo lo si fa acquisendo il "lock" (sarebbe più corretto dire il monitor ma tendo generalmente a dire lock) su un oggetto in modo che solo un thread per volta possa eseguire il pezzo di codice che esegue i 3 print.
Visto che puoi solo cambiare nel try, dovrai per forza usare un blocco synchronized, ovvero un blocco { } che usa la parola chiave synchronized per acquisire il lock su un oggetto specifico.
Ed ecco il punto: quale oggetto? Presta attenzione, deve essere un oggetto che sia condiviso tra i due thread, altrimenti se fossero due distinti non avresti più la mutua-esclusione.
Quindi prova a pensare: puoi usare come oggetto di lock il this? Pensaci bene.
Se non potessi usare il this, allora cosa potresti usare?![]()