DeadLock e le sue cause - 1

"Ciao, Amico!"

"Oggi ti dirò cos'è lo stallo."

"Ehi, mi hai già parlato di una cosa del genere."

"Sì, l'ho fatto. Ma oggi considereremo l'argomento più in dettaglio."

"Nel caso più semplice, il deadlock coinvolge due thread e due oggetti mutex. Un blocco reciproco si verifica quando:"

A) Ogni thread deve acquisire entrambi i mutex.

B)  Il primo thread ha acquisito il primo mutex ed è in attesa del rilascio del secondo.

C)  Il secondo thread ha acquisito il secondo mutex ed è in attesa del rilascio del primo.

"Ecco alcuni esempi:

Esempio
 public class Student
{
 private ArrayList friends = new ArrayList();

 public synchronized ArrayList getFriends()
 {
  synchronized(friends)
  {
   return new ArrayList(friends);
  }
 }

 public synchronized int getFriendsCount()
 {
  return friends.size();
 }

 public int addFriend(Student student)
 {
  synchronized(friends)
  {
   friends.add(student)
   return getFriendsCount ();
  }
 }
}

"Supponiamo che un thread chiami il metodo getFriends , acquisisca il mutex dell'oggetto this e quindi acquisisca il mutex dell'oggetto friends ."

"Nel frattempo, un secondo thread chiama il metodo addFriend , acquisisce il mutex dell'oggetto friends e quindi acquisisce il mutex dell'oggetto this (durante una chiamata a getFriendsCount )."

"All'inizio andrà tutto bene, ma come afferma la legge di Murphy: tutto ciò che può andare storto andrà storto. Si verificherà inevitabilmente una situazione in cui il primo thread avrà il tempo di acquisire solo un mutex e il secondo thread acquisirà il secondo mutex in quel preciso momento. Si bloccheranno così, aspettando per sempre che l'altro thread rilasci il mutex."

"Ho deciso di citare un altro semplice esempio che ho trovato in un libro:"

Esempio
class KnightUtil
{
 public static void kill(Knight knight1, Knight knight2)
 {
  synchronized(knight1)
  {
   synchronized(knight2)
   {
    knight2.live = 0;
    knight1.experience += 100;
   }
  }
 }
}

"C'è un gioco in cui due cavalieri si combattono l'un l'altro. Un cavaliere uccide l'altro. Questo comportamento si riflette nel metodo di uccisione . Gli vengono passati due oggetti cavaliere.

"In primo luogo, proteggiamo entrambi gli oggetti in modo che nessun altro possa modificarli".

"Il secondo cavaliere muore (HP = 0)"

"Il primo cavaliere guadagna 100 XP."

"Sembra tutto a posto, ma potrebbero esserci situazioni in cui il secondo cavaliere attacca il primo nello stesso momento. Questo metodo è anche chiamato per il secondo cavaliere, ma gli oggetti del cavaliere vengono passati in un ordine diverso."

"Vuoi dire che non abbiamo nemmeno bisogno di più metodi per ottenere lo stallo?"

"Giusto. A volte basta un semplice metodo per bloccare i thread e l'intero programma."

"Sì, immagino che questo fenomeno si verifichi più spesso di quanto pensassi. Grazie, Ellie."