DeadLock i jego przyczyny - 1

Witaj Amigo!

Dzisiaj powiem Ci, czym jest impas (DeadLock) - wzajemne blokowanie.

„Więc już powiedziałeś coś takiego.

- Tak, było. Ale dzisiaj rozważymy ten temat bardziej szczegółowo.

W najprostszym przypadku w zakleszczeniu uczestniczą dwa wątki i dwa obiekty mutex. Zakleszczenie występuje, gdy:

A)  Każdy wątek w procesie pracy musi przechwycić oba muteksy.

B)  Pierwszy wątek przechwycił pierwszy muteks i czeka na zwolnienie drugiego.

C)  Drugi wątek przechwycił drugi muteks i czeka na zwolnienie pierwszego.

Przykłady:

Przykład
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();
  }
 }
}

Powiedzmy, że pierwszy wątek o nazwie  metoda getFriends , najpierw pobrałby  muteks tego obiektu , a następnie  muteks obiektu znajomych .

Następnie drugi wątek wywołał  metodę addFriend , najpierw pobiera muteks obiektu  friends , a następnie muteks tego obiektu (podczas wywoływania getFriendsCount ).

Na początku wszystko będzie dobrze, ale jak mówi prawo Murphy'ego - jeśli kłopoty mogą się zdarzyć, to się zdarzają. Nieuchronnie dojdzie do sytuacji, w której pierwszy wątek będzie miał czas na przechwycenie tylko jednego muteksu, a drugi wątek przechwyci w tym czasie drugi. Będą wisieć na zawsze, czekając, aż jeden z nich pierwszy zwolni muteks.

Kolejny prosty przykład, znaleziony w książce:

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

Jest taka gra, w której dwóch rycerzy walczy ze sobą. Jeden rycerz zabija drugiego. To zachowanie jest odzwierciedlone w  metodzie kill . Przechodzą tam dwa obiekty rycerskie.

Po pierwsze, chronimy oba obiekty, aby nikt inny nie mógł ich zmienić.

Drugi rycerz umiera (live=0)

Pierwszy rycerz otrzymuje +100 doświadczenia.

Wszystko wydaje się być w porządku, ale czasami może dojść do sytuacji, gdy w tym czasie drugi rycerz zaatakuje pierwszego. Ta metoda jest również nazywana dla niego, ale rycerze są przekazywani w innej kolejności.

- Tj. nie potrzebujemy nawet wielu metod, aby uzyskać impas?

- Tak. Czasami wystarczy jedna prosta metoda, w której mogą już zachodzić procesy prowadzące do zamrożenia wątków i całego programu.

Tak, okazuje się, że zjawisko to występuje częściej niż myślałem. Dzięki Ellie.