wielowątkowość w javie

0
 public int balance() {
    try {
      lock.lock();
      number++;
      System.out.print("*");
      number--;
      return number;
    } finally {
        lock.unlock();
    }
  }

Dlaczego użyty jest tu blok try, finally?
Co byłoby jeżeli byłoby tak:

 public int balance() {

      lock.lock();
      number++;
      System.out.print("*");
      number--;
      return number;

       lock.unlock();
    
  }
1

Primo: masz unreachable code.
Secundo: try/ finally jest wymagane, no chyba, że chcesz by exceptiony (tutaj w metodzie System.out.println) powodowały u ciebie wiszące locki.

1

lock.unlock() nie zostanie wywołane, ponieważ jest po return. Nie jestem nawet pewny, czy w ogóle się skompiluje - NetBeans np. krzyczy mi, że jest błąd.

0

Secundo: try/ finally jest wymagane, no chyba, że chcesz by exceptiony (tutaj w metodzie System.out.println) powodowały u ciebie wiszące locki.

Dobrze, to załóżmy, że pojawiły się takie wątki. Co się wówczas dzieje, jeżeli sytuacja wygląda tak jak w pierwszym przypadku, a co w drugim.
Uznajmy, że w drugim przypadku nie ma tego return, bo to rzeczywiście robi kod nieosiągalny.
dzięki za odpowiedzi :)

1

Jeśłi masz try/finally to kod z finally zawsze jest odpalany. Jeśli w środku try masz return to blok finally jest odpalany tuż przed returnem - no chyba że masz exception to finally będzie odpalane tuż przed powrotem z funkcji. Stąd wynika, iż w przypadku exceptiona lock będzie zwolniony jeśli będzie blok try/finally, ale będzie wiszący jak nie wstawisz bloku try/finally.

0

no dobrze. No to załóżmy, że funkcja w try{} zwraca wartość. Wg tego co napisałeś, najpierw wykona się blok finally{}. Zatem w szczególności nastąpi otwarcie monitora.
( locker.unlock()) . Zatem co jeżeli bo finally nastątpi przerwanie i jakiś inny wątek uzyska dostęp i zmieni nam wartość zwracaną?

1

Nie jestem pewien co się stanie. JVM jest maszyną stosową według specyfikacji, więc możliwe, że kopia 'number' zostanie włożona na stos przed wywołaniem bloku finally, ale nie dam sobie za to nic uciąć. Najbezpieczniej byłoby zrobić kopię ręcznie i/lub dowiedzieć się jak JVM się zachowa.

1

Odlozenie na stosie wartości zwracanej z metody wydarzy się przed zwolnieniem locka w finally. Zachowanie to jest zagwarantowane przez happens-before dla monitorExit. W praktyce JVM odkłada wartość zwracana na stosie zmiennych lokalnych, wykonuje unlock(), a następnie return. Można sobie to sprawdzić analizując bytecode dla każdego takiego przypadku.
Oznacza to że możliwy jest scenariusz, w którym pomiędzy zwolnieniem locka a return inny wątek przeprowadzi całą operacje od początku do końca, wobec czego wartość zwrócona przez wątek bieżący będzie juz nieaktualna.

0

Dziękuję :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1