Java.lang.Thread.State'i Anlamak: BEKLEME (park etme)


91

İlk olarak, gerçekten aptalca bir soru, beklemenin ne anlama geldiğini merak ediyordum. İplik park edilmeyi mi bekliyor yoksa park edilmiş ve bu nedenle bekleme durumunda mı? Ve bu park etme gerçekleştiğinde, ne kadar cpu / bellek kaynağı alınır? İpliği park etmenin amacı nedir?

İkinci olarak, java thread API'deki park yöntemine bakarak

İzin mevcut olmadığı sürece iş parçacığı zamanlama amaçları için geçerli iş parçacığını devre dışı bırakır.

İzin mevcutsa tüketilir ve çağrı hemen geri döner; aksi halde mevcut iş parçacığı iş parçacığı zamanlama amaçları için devre dışı kalır ve üç şeyden biri olana kadar uykuda kalır .....

İngilizce benim ana dilim değil, bu yüzden anlamakta güçlük çekiyorum, 'konuyu park etme izni' olarak 'izin vermeyi' amaçladım, bu yüzden aşağıdaki sorular:

  • bunun anlamı nedir, 'izin' nedir ve bu izinleri kim ve nasıl kontrol ediyor?
  • Bu ne anlama geliyor: 'izin varsa o zaman tüketilir', 'park mı ediliyor'?
  • ardından, eğer ikinci nokta doğruysa, o halde 'park etme' ve 'uykuda yatıyor' arasındaki fark nedir? İznim varsa sonsuza kadar park edebilirim ve yoksa 'uykuda mı' yapabilirim?

Teşekkürler

Yanıtlar:


37

İzin, yürütmeye devam etme izni anlamına gelir. Park etme, izin alınana kadar infazın durdurulması anlamına gelir.

Semaphoreİzinlerinin aksine , izinleriLockSupport iş parçacıklarıyla ilişkilidir (yani izin belirli bir iş parçacığına verilir) ve birikmez (yani iş parçacığı izni tükettiğinde iş parçacığı başına yalnızca bir izin olabilir, kaybolur).

Bir iş parçacığına arayarak izin verebilirsiniz unpark(). Bir iş parçacığı, çağrı yoluyla izin kullanılabilir olana (veya iş parçacığı kesilene veya zaman aşımı süresi dolana, vb park().) İzin mevcut olduğunda, park edilmiş iş parçacığı onu tüketir ve bir park()yöntemden çıkar .


2
Tekrar varsayarsak, eğer A iş parçacığı B iş parçacığı için 'park' çağrısı yapıyor, ancak izin mevcutsa, bu 'B park edilemez' ise, o zaman A tarafından yapılan çağrı geri dönüyor ve B park edilmiyor. Aksi takdirde, izin olmadığında, B itaat etmek zorundadır. Öyleyse, bekleme (park etme) "A beni park etmeye çalışıyor çünkü iznim yok ama şu anda bunu yapamıyorum, bu yüzden A'yı da bloke ediyorum" anlamına mı geliyor? Bu uzun cümle için özür dilerim. Sanırım bu bekleme oldukça kaynak tüketiyor. Hala tüm izin işini kimin yönettiğini merak ediyorum. Kimin / neyin, bazı iş parçacığının izne sahip olduğuna, diğerlerinin olmadığına karar veriyor.
Leonardo

2
@Leonardo: Bir iş parçacığı yalnızca kendi kendine park edebilir, diğer konuları park etmenin bir yolu yoktur. Yani, arama park(), "Başka bir iş parçacığı arayarak bana izin verene kadar yürütmemi askıya almak istiyorum" anlamına gelir unpark().
axtavt

Yani bir iş parçacığı diğer konuları park edemez, ancak diğer konular tarafından park edilebilir mi? Bu doğru mu ? Peki, bu park ne zaman olacak? Belki bir iş parçacığının şu anda yapacak bir işi yoktur ve bunu kontrol etmenin bir yolu da sürekli iznine bakmak mıdır? Bu, örneğin arka plan iş parçacığı için uygun olacaktır.
Leonardo

Ayrıca, BEKLİYOR (park etme), park edilmeyi beklediği veya park edildikten sonra bekleme durumunda olduğu anlamına mı geliyor? Üzgünüm, bunun aptalca bir soru olduğunu biliyorum :-)
Leonardo

3
@Leonardo: Park edildikten sonra bekleme durumu demektir.
axtavt

11

Java İş Parçacığı Durumu Belgelerine göre , bir iş parçacığı BEKLEME durumuna üç nedenden dolayı gidebilir:

  1. Zaman aşımı olmadan Object.wait
  2. Zaman aşımı olmadan Thread.join
  3. LockSupport.park

Bir İş Parçacığı üzerinde bir park yöntemini çağırdığınızda, izin mevcut olmadığı sürece iş parçacığını zamanlama amaçları için devre dışı bırakır. Zaten mevcut değilse, verilen iş parçacığı için izni kullanılabilir hale getirmek için unpark yöntemini çağırabilirsiniz.

Böylece, Thread'ınız LockSupport.park tarafından BEKLENİYOR modunda olduğunda, sizi BEKLİYOR (park etme) olarak gösterecektir.

Lütfen sadece mevcut İş Parçacığı üzerinde park arayabileceğinizi unutmayın. Bu, Üretici-Tüketici Tasarım Modelini uygulamak için çok yararlı bir mekanizmadır.


3

İzni açıkladığı sınıf açıklamasından ( LockSupport javadoc'un üst kısmında ):

Bu sınıf, onu kullanan her iş parçacığı ile bir izin (Semafor sınıfı anlamında) ilişkilendirir. Park etme çağrısı, izin varsa , süreçte [izni] tüketerek hemen geri dönecektir ; aksi takdirde [park etme çağrısı] engellenebilir. Parktan çıkarma çağrısı, izin zaten mevcut değilse, izni kullanılabilir hale getirir. (Semaforların aksine, izinler birikmez. En fazla bir tane vardır.)

( İngilizce konuşanlar için okumayı kolaylaştırmak için [metni] genişlettim .)

Umarım daha derin bir anlayışa sahip biri bu konuyu detaylandırabilir.Axtavt'ın cevabına bakın.

Son bir not olarak, javadoc'tan son bir alıntı:

Bu yöntemler, üst düzey senkronizasyon yardımcı programları oluşturmak için araçlar olarak kullanılmak üzere tasarlanmıştır ve çoğu eşzamanlılık kontrol uygulaması için kendi başlarına yararlı değildir.


3

Belgeleri okurken bulamadığım bu soruyu tekrar gözden geçirmemi sağlayan kısım şuydu:

İzin mevcutsa tüketilir ve çağrı hemen geri döner ...

Yani ne zaman izin "müsait" olduğunu kim ve nasıl hemen tüketilen alabilir böylece, kullanılabilir hale getirir? Bunu öğrenmek bir şekilde önemsizdi:

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 kendisi için konuşuyor thread, çalışıyor ama henüz çağrılmadı LockSupport.park, diğer bazı iş parçacıkları LockSupport.unparkise onu çağırır - böylece izni kullanılabilir hale getirir. Ondan sonra ararızLockSupport.park ve izin mevcut olduğu için hemen geri döner.

Bir kez düşündüğünüzde, bu biraz tehlikelidir, iş parçacıklarınızı kontrol etmediğiniz bir koda maruz bırakırsanız ve bu kod LockSupport.unparksizden parksonra çağrılırsa işe yaramayabilir.


Çok iyi bir nokta, etkinlik veren bir iznin - yani unpark () 'ı çağırmanın - yalnızca bir iş parçacığı park edildiğinde geçerli olduğunu düşünürdüm.
Alfred Xiao

@AlfredXiao kabul etti, bu beni de şaşırtan bir şey, ama sanırım mantıklı geliyor.
Eugene

1

Anladığım kadarıyla, "izin" yalnızca bir İş Parçacığının "park edilmemiş" olup olmadığını gösteren bir nesnedir. Ve bu İpliğin kendisi tarafından kontrol edilir (veya bir İpliği park etmeye çalıştığınızda de JRE) "tüketildi" şeyi, iznin kaybolduğunu ve İpliğin devre dışı olmadığını anlıyorum.

Bence multithreading hakkında biraz daha fazla şey öğrenmelisiniz .. Bunu "permit" adı verilen Nesneleri olan bir dağıtıcı olarak düşünün. Bir İpliğe park etmesini söyleyin ve İplik dağıtıcıyı kontrol edin, bir "izin" varsa, İplik onu alır ve ayrılır (park etmeden). Dağıtıcıda "izin" yoksa, İplik bir "izin" mevcut olana kadar park edilir (ve dağıtıcıya bir "izin" koyabilirsiniz unpark.

CPU / bellek kullanımına gelince, bunun işletim sistemine vb. Bağlı olduğunu düşünüyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.