Zrozumienie java.lang.Thread.State: WAITING (parking)


90

Po pierwsze, naprawdę głupie pytanie, zastanawiałem się tylko, co oznacza czekanie „parking”? Czy wątek czeka na zaparkowanie, czy właśnie został zaparkowany i dlatego jest w stanie oczekiwania? A kiedy to nastąpi, ile zasobów procesora / pamięci jest pobieranych? Jaki jest cel parkowania wątku?

Po drugie, patrząc na metodę parkowania w interfejsie API wątków Java

Wyłącza bieżący wątek do celów planowania wątków, chyba że zezwolenie jest dostępne.

Jeśli zezwolenie jest dostępne, jest zużywane i wezwanie natychmiast powraca; w przeciwnym razie bieżący wątek zostanie wyłączony do celów planowania wątków i pozostanie w stanie uśpienia, dopóki nie nastąpi jedna z trzech rzeczy .....

Angielski nie jest moim głównym językiem, więc mam pewne trudności ze zrozumieniem tego, zamierzałem „zezwolić” jako rodzaj „pozwolenia na zaparkowanie wątku”, więc następujące pytania:

  • jakie jest to znaczenie, co to jest „zezwolenie” i kto i jak sprawdza te zezwolenia?
  • Co to znaczy: „jeśli zezwolenie jest dostępne, to jest zużywane”, czy jest „zaparkowane”?
  • a następnie, jeśli drugi punkt jest prawdziwy, jaka jest różnica między „parkowaniem” a „uśpionymi kłamstwami”? Jeśli mam pozwolenie, mogę zaparkować go na zawsze, a jeśli nie, mogę go „uśpić”?

Dzięki

Odpowiedzi:


36

Zezwolenie oznacza pozwolenie na dalsze wykonywanie. Parkowanie oznacza wstrzymanie wykonania do czasu uzyskania pozwolenia.

W przeciwieństwie do Semaphorezezwoleń, zezwolenia LockSupportsą powiązane z wątkami (tj. Zezwolenie jest udzielane określonemu wątkowi) i nie kumuluje się (tzn. Może być tylko jedno zezwolenie na wątek, gdy wątek zużywa zezwolenie, znika).

Możesz zezwolić na wątek dzwoniąc unpark(). Wątek może zawiesić swoje wykonywanie do momentu uzyskania zezwolenia (lub przerwania wątku, wygaśnięcia limitu czasu itp.) Przez wywołanie park(). Gdy zezwolenie jest dostępne, zaparkowany wątek zużywa go i zamyka park()metodę.


2
Tak więc, zakładając ponownie, jeśli wątek A wywołuje „zaparkuj” dla wątku B, ale zezwolenie jest dostępne, czyli „B nie można zaparkować”, wówczas wywołanie wykonane przez A po prostu powróci, a B nie zostanie zaparkowany. W przeciwnym razie, gdy zezwolenie nie jest dostępne, B musi być posłuszny. Czy więc czekanie (parkowanie) oznacza „A próbuje mnie zaparkować, ponieważ nie mam pozwolenia, ale nie mogę tego teraz zrobić, więc blokuję również A”? Przepraszam za to długie zdanie. Przypuszczam, że to czekanie pochłania dużo zasobów. Nadal się zastanawiam, kto zarządza całym pozwoleniem. Kto / co decyduje, że niektóre wątki mają pozwolenie, a inne nie.
Leonardo

2
@Leonardo: Wątek może zaparkować tylko sam, nie ma możliwości zaparkowania innych wątków. Tak więc wołanie park()oznacza „Chcę zawiesić moją egzekucję do czasu, aż jakiś inny wątek da mi pozwolenie przez telefon unpark()”.
axtavt

Czyli wątek nie może zaparkować innych wątków, ale może zostać odparkowany przez inne wątki? Czy to jest poprawne ? Więc kiedy to się dzieje? Może wątek nie ma w tej chwili pracy do wykonania, a sposobem na sprawdzenie tego jest ciągłe sprawdzanie jego zezwolenia? Byłoby to odpowiednie na przykład dla wątku demona.
Leonardo,

Ponadto komunikat OCZEKIWANIE (parkowanie) oznacza, że ​​czeka na zaparkowanie lub jest w stanie oczekiwania po zaparkowaniu? Przepraszam, wiem, że to głupie pytanie :-)
Leonardo

3
@Leonardo: Oznacza stan oczekiwania po zaparkowaniu.
axtavt

11

Zgodnie z dokumentacją stanu wątku java , wątek może przejść do stanu OCZEKIWANIE z trzech powodów:

  1. Object.wait bez limitu czasu
  2. Thread.join bez limitu czasu
  3. LockSupport.park

Gdy wywołujesz metodę parkowania w wątku, wyłącza wątek na potrzeby planowania wątków, chyba że zezwolenie jest dostępne. Możesz wywołać metodę unpark, aby udostępnić zezwolenie dla danego wątku, jeśli nie było jeszcze dostępne.

Tak więc, gdy Twój wątek jest w trybie OCZEKIWANIA przez LockSupport.park, wyświetli się jako OCZEKIWANIE (parking).

Pamiętaj, że możesz zadzwonić do parkowania tylko w bieżącym wątku. Jest to bardzo pomocny mechanizm we wdrażaniu wzorca projektowego producent-konsument.


3

Z opisu klasy (na górze LockSupport javadoc ), gdzie opisuje zezwolenie:

Ta klasa kojarzy się z każdym wątkiem, który jej używa, zezwoleniem (w sensie klasy Semaphore). Wezwanie do parkowania powróci natychmiast, jeśli pozwolenie będzie dostępne, wykorzystując [pozwolenie] w trakcie; w przeciwnym razie [wezwanie do parkowania] może zostać zablokowane. Wezwanie do odparkowania udostępnia zezwolenie, jeśli nie było jeszcze dostępne. (Jednak w przeciwieństwie do Semaforów, pozwolenia nie kumulują się. Jest co najwyżej jedno).

(Rozszerzyłem [tekst], aby był łatwiejszy do czytania dla osób nie mówiących po angielsku).

Miejmy nadzieję, że ktoś z głębszym zrozumieniem może to rozwinąć. Zobacz odpowiedź axtavt.

Na koniec ostatni cytat z javadoc:

Metody te są przeznaczone do użytku jako narzędzia do tworzenia narzędzi do synchronizacji wyższego poziomu i same w sobie nie są przydatne w większości aplikacji sterujących współbieżnością.


3

Część, która sprawiła, że ​​powróciłem do tego pytania, którego nie mogłem obejść podczas czytania dokumentacji, to:

Jeśli zezwolenie jest dostępne, jest zużywane i połączenie natychmiast wraca ...

Kiedy więc pozwolenie jest „dostępne”, kto i jak je udostępnia, aby mogło zostać natychmiast wykorzystane? To było w jakiś sposób trywialne, aby się dowiedzieć:

public static void main(String[] args) {

    Thread parkingThread = new Thread(() -> {
        System.out.println("Will go to sleep...");
        sleepTwoSeconds();
        System.out.println("Parking...");
        // this call will return immediately since we have called  LockSupport::unpark
        // before this method is getting called, making the permit available
        LockSupport.park();
        System.out.println("After parking...");
    });

    parkingThread.start();

    // hopefully this 1 second is enough for "parkingThread" to start
    // _before_ we call un-park
    sleepOneSecond();
    System.out.println("Un-parking...");
    // making the permit available while the thread is running and has not yet
    // taken this permit, thus "LockSupport.park" will return immediately
    LockSupport.unpark(parkingThread);

}

private static void sleepTwoSeconds() {
    try {
        Thread.sleep(1000 * 2);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

private static void sleepOneSecond() {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}    

Kod mówi sam za siebie, program threaddziała, ale jeszcze nie został wywołany LockSupport.park, podczas gdy inny wątek go wywołuje LockSupport.unpark- w ten sposób udostępniając zezwolenie. Po tym dzwonimy, LockSupport.parka ten wraca natychmiast, ponieważ zezwolenie jest dostępne.

Kiedy się nad tym zastanowisz, jest to trochę niebezpieczne, jeśli narażasz swoje wątki na jakiś kod, którego nie kontrolujesz, a ten kod wywołuje, LockSupport.unparkgdy ty parkpotem to robisz - może to nie działać.


Bardzo dobra uwaga, pomyślałbym, że zezwolenie na czynność - tj. Wywołanie unpark () - ma znaczenie tylko wtedy, gdy zaparkowany jest wątek.
Alfred Xiao

@AlfredXiao zgodził się, to też mnie zaskoczyło, ale wydaje mi się, że ma to sens.
Eugene

1

Jak rozumiem, „zezwolenie” to po prostu obiekt, który wskazuje, czy wątek można „odparkować”, czy nie. I jest to sprawdzane przez sam Wątek (lub de JRE, gdy próbujesz zaparkować Wątek). „Jest zużyty”, rozumiem, że zezwolenie znika, a Wątek nie jest wyłączany.

Myślę, że powinieneś dowiedzieć się trochę więcej o wielowątkowości. Pomyśl o tym jak o dozowniku obiektów zwanych „pozwoleniem”. Mówisz Nici, aby zaparkowała, a Nić sprawdza dozownik, jeśli jest „zezwolenie”, Nić bierze ją i wychodzi (bez parkowania). Jeśli w dozowniku nie ma „zezwolenia”, nić jest zaparkowana do czasu uzyskania „zezwolenia” (i można umieścić „zezwolenie” w dozowniku za pomocą unpark.

Jeśli chodzi o użycie procesora / pamięci, myślę, że zależy to od systemu operacyjnego itp ...

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.