Sto sviluppando un applicazione che prevede di gestire concorrentemente una rete ferroviaria (progetto didattico): diverse stazioni (Thread) sono collegate tra loro attraverso un unico binario. I treni che "corrono" nella rete non devono scontrarsi: se un treno deve andare dalla stazione A alla stazione B, e viceversa, un treno deve andare dalla stazione B alla stazione A, ciò deve accadere in tempi diversi.
Le stazioni quindi comunicano tra di loro attraverso RMI per evitare che vi siano collisioni.
Ecco come gestisco la fase di comunicazione per evitare collisioni tra 2 stazioni generiche A e B:

//prendo il lock sul binario locale che porta a B
Id.getAdjacentTrainStation().elementAt(index).lock .lock();
//chiedo alla stazione B tramite RMI il lock al suo binario che porta ad A
boolean ret = Id.getAdjacentTrainStation().elementAt(index).getR miLinkTrainStation().askTrainStationLock(Id.getNam e());
if(ret==true) {
//metodo che invia il treno via RMI verso B, dato che è stato preso il possesso del binario da A
Id.getAdjacentTrainStation().elementAt(index).getR miLinkTrainStation().getTrain(treno,Id.getName()); inviato=true;
Id.getAdjacentTrainStation().elementAt(index).lock .unlock();
}

ecco la funzione askTrainStationLock(..):

public boolean askTrainStationLock(String stazione)throws RemoteException{
if(getStartedStation()==true && getActiveService()==true) {
//ottengo l'indice della stazione che richiede il lock da un vettore che memorizza tutte le stazioni che sono collegate rispetto alla stazione locale: in questo modo B riesce a sapere informazioni su A
int index=Id.getAdjacentTrainStationIndex(stazione);
if(index!=-1) {
boolean locked=Id.getAdjacentTrainStation().elementAt(inde x).lock.tryLock();
return locked;
}
}

return false;
}

ecco la funzione getTrain(..):

public void getTrain(Treno treno, String mittente) throws RemoteException{
//aggiungo in un vettore che memorizza i passeggieri in attesa tutti i passeggieri giunti col treno
Id.lock.lock();
waitingPassengerList.addAll(treno.getPassengers()) ;
//notifico al thread che gestisce la stazione il fatto che siano giunti altri passeggieri
Id.waitingPassenger.signalAll();//risveglio il servizio, nel caso sia in attesa
Id.lock.unlock();
//rilascio il lock locale sul binario che porta da A a B. Mi rilancia l'eccezione questa riga
Id.getAdjacentTrainStation().elementAt(Id.getAdjac entTrainStationIndex(mittente)).lock.unlock();
addData("sono arrivati dei passeggieri da "+mittente+"\n");
}

E qua il dubbio: l'eccezione IllegalMonitorStateException viene rilanciata solo raramente (1 volta ogni 10 esecuzioni, con 7 stazioni che lavorano in parallelo, con circa 20 passeggieri nella rete ferroviaria). Mi è venuto il dubbio: se un thread A chiede un lock via RMI in una comunicazione C1 a un thread B, in una comunicazione seguente C2 con B attraverso un altra chiamata RMI garantisce il fatto che io abbia il lock su quell'oggetto?