DeadLock и причините за него - 1

„Здрасти, Амиго!“

„Днес ще ви кажа Howво е безизходица.“

— Хей, ти вече ми каза за нещо подобно.

"Да, направих. Но днес ще разгледаме темата по-подробно."

"В най-простия случай блокирането включва две нишки и два mutex обекта. Взаимно заключване възниква, когато:"

A) Всяка нишка трябва да придобие и двата мутекса.

B)  Първата нишка е придобила първия мютекс и чака вторият да бъде освободен.

C)  Втората нишка е придобила втория мютекс и чака първият да бъде освободен.

"Ето няколко примера:

Пример
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 ();
  }
 }
}

„Да предположим, че една нишка извиква метода getFriends , придобива мутекса на този обект и след това придобива мутекса на обекта приятели .“

„Междувременно втора нишка извиква метода addFriend , придобива мутекса на обекта friends и след това придобива мутекса на този обект (по време на извикване на getFriendsCount ).“

„Първоначално всичко ще бъде наред, но Howто гласи законът на Мърфи: всичко, което може да се обърка, ще се обърка. Неизбежно ще възникне ситуация, при която първата нишка ще има време да придобие само един мютекс, а втората нишка ще придобие втория mutex точно в този момент. Те ще висят така, вечно чакайки другата нишка да освободи mutex."

„Реших да цитирам друг прост пример, който намерих в една книга:“

Пример
class KnightUtil
{
 public static void kill(Knight knight1, Knight knight2)
 {
  synchronized(knight1)
  {
   synchronized(knight2)
   {
    knight2.live = 0;
    knight1.experience += 100;
   }
  }
 }
}

„Има игра, в която двама рицари се бият помежду си. Единият рицар убива другия. Това поведение е отразено в метода на убийство . Към него се подават два предмета на рицаря.

„Първо, защитаваме и двата обекта, така че никой друг да не може да ги промени.“

„Вторият рицар умира (HP = 0)“

„Първият рицар печели 100 XP.“

„Всичко изглежда добре, но може да има ситуации, при които вторият рицар атакува първия по едно и също време. Този метод се извиква и за втория рицар, но обектите на рицаря се предават в различен ред.“

„Искате да кажете, че дори не се нуждаем от множество методи, за да стигнем до безизходица?“

"Точно така. Понякога е необходим само един прост метод, за да предизвика нишките и цялата програма да висят."

„Да, предполагам, че това явление се случва по-често, отколкото си мислех. Благодаря, Ели.“