BEKLE ve ENGELLENMİŞ iş parçacığı durumları arasındaki fark


102

İplik durumu BEKLEME ve BLOKE edilmiş iplik durumu arasındaki fark nedir?

Thread.State belgeleri :

Engellendi
Bir monitör kilidi bekleyen iş parçacığı bu durumdadır.

Bekleniyor
Başka bir iş parçacığının belirli bir eylemi gerçekleştirmesini süresiz olarak bekleyen bir iş parçacığı bu durumda

bana farkı açıklamıyor.


bu konudaki yanıtı kontrol edin stackoverflow.com/questions/2534147/java-thread-wait-blocked ayrıca bu bağlantı daha fazla açıklama sağlayabilir geekexplains.blogspot.cz/2008/07/…
Abdul

Geekexplains bağlantısı @Abdul, bir iş parçacığının Object.wait () 'i çağırarak engellenmiş bir duruma geçebileceğini söylüyor, bu doğru değil mi?
Beşten Fazla

oracle belgelerine göre docs.oracle.com/javase/6/docs/api/java/lang/… : Aşağıdaki yöntemlerden birinin çağrılması nedeniyle bir iş parçacığı bekleme durumunda: Zaman aşımı olmadan Object.wait, Thread.join zaman aşımı olmadan, LockSupport.park
Abdul

Kayıt için, değiştirmeyi düşünmeniz durumunda Flavio'nun cevabının Ankit'ten biraz daha iyi olduğunu düşünüyorum.
Grey

Yanıtlar:


80

Bir iş parçacığı wait(), bir Nesneyi çağırdığında bekleme durumuna geçer . Buna Bekleme Durumu denir . Bir iş parçacığı bekleme durumuna ulaştığında, başka bir iş parçacığı çağırana kadar notify()veya notifyAll()nesne üzerinde beklemesi gerekecektir .

Bu iş parçacığı bildirildikten sonra çalıştırılabilir olmayacaktır. Diğer iş parçacığı da bildirilmiş (kullanılarak notifyAll()) veya ilk iş parçacığı işini bitirmemiş olabilir, bu nedenle şansı elde edilene kadar hala engellenir. Buna Engellenmiş Durum denir . Bir iş parçacığı nesne üzerinde kilit almaya çalıştığında ve başka bir iş parçacığı zaten kilidi tuttuğunda bir Engellenmiş durumu ortaya çıkar.

Diğer iş parçacıkları ayrıldıktan ve bu iş parçacığı şansı bir kez, Çalıştırılabilir duruma geçer, bundan sonra JVM iş parçacığı mekanizmasına göre uygun alma işi olur ve çalışma durumuna geçer.


2
Bunu çok daha iyi açıkladınız, çünkü bir iş parçacığının bu iki duruma ulaşma sırasını açıkladınız, bu da her iki durumu ayrı ayrı açıklamaktan ("Beşten Fazla"
yanıtıyla yapılır

7
Web talebinde bulunan durum diyagramlarının çoğunun (tümü?) Neden, notify () / notifyAll () 'ın ENGELLENMİŞ yerine RUNNABLE ile sonuçlandığını merak edenler için: stackoverflow.com/questions/28378592/…
Niklas Peter

Yalnızca bir iş parçacığı olduğunu ve milis cinsinden bir süre beklediğini varsayalım; şimdi bir iş parçacığının bekleme durumundan çalıştırılabilir duruma geçmesi mümkün müdür? Burada başka hiçbir iş parçacığı kilitlenmediğinden, yalnızca tek iş parçacığı olduğundan beri?
Kanagavelu Sugumar

Süre geçtikten sonra çalıştırılabilir duruma geri dönecek bir bekleme (zaman) yöntemi vardır. Ancak zaman belirtilmezse, diğer iş parçacığı bildirimde bulunana veya iş parçacığı kesilene kadar bekleyecektir.
Ankit Bansal

2
Cevabınız güzel, ancak bir kilit almaya çalıştığınızda Engellenmiş bir duruma girebileceğinizi tam olarak açıklamıyor. Sinyal / bildirim ile hiçbir ilgisi olması gerekmez.
Gray

90

Fark nispeten basit.

Durumda BLOCKED, bir iş parçacığı bir synchronizedbloğa girmek üzeredir , ancak synchronizedaynı nesne üzerindeki bir bloğun içinde şu anda çalışan başka bir iş parçacığı vardır . İlk iş parçacığı daha sonra ikinci iş parçacığının bloğundan çıkmasını beklemelidir.

Durumda WAITING, bir iş parçacığı başka bir iş parçacığından bir sinyal bekliyor. Bu genellikle Object.wait(), veya Thread.join(). İş parçacığı, başka bir iş parçacığı çağırana Object.notify()veya ölene kadar bu durumda kalacaktır .


2
Sadece bir iş parçacığının kendisinin onu beklemeye alabileceğini söylemek doğru mu? Thread-B, Thread-A'nın BEKLEME durumuna geçmesini sağlayabilir mi?
Beşten Fazla

1
Nadiren Object.wait()doğrudan kullanırsınız , ancak sonunda WAITING, iki iş parçacığının koordine edilmesi gerektiğinde, kilitler, engelleme kuyrukları vb.
Flavio

1
Kişisel deneyime göre, IO için bekleyen iş parçacıkları (örneğin bir Soketten okumak) RUNNINGdurumdadır.
Flavio

4
Java8 doc for Thread.Statediyor, "... Bu durumlar, herhangi bir işletim sistemi iş parçacığı durumunu yansıtmayan sanal makine durumlarıdır." Başka bir deyişle, JVM, Java kodunu çalıştıran bir iş parçacığı, bir sistem çağrısının geri dönmesini bekleyen bir iş parçacığı veya bir zaman dilimini bekleyen bir iş parçacığı arasındaki farkı umursamaz. Bunların hepsi RUNNABLE, JVM'nin söz konusu olduğu ölçüde.
Solomon Slow

3
Bir iş parçacığı WAITINGdurumdan BLOCKEDçıktığında, beklediği nesne ile ilişkili kilidi elde edene kadar önce duruma gitmesi gerektiğini eklemek güzel olabilir .
Gray

23

Engellenen ve bekleme durumları arasındaki önemli fark, zamanlayıcı üzerindeki etkidir. Engellenmiş durumdaki bir iş parçacığı kilit için yarışıyor; bu iş parçacığı yine de zamanlayıcının hizmet vermesi gereken bir şey olarak sayılır, muhtemelen programlayıcının çalışan iş parçacıkları vermesi için ne kadar süre vereceğine dair kararlarında hesaba katılır (böylece iş parçacıklarının kilit üzerindeki engelleme şansı verebilir).

Bir iş parçacığı bekleme durumunda olduğunda, sisteme yüklediği stres en aza indirilir ve programlayıcının bunun için endişelenmesine gerek kalmaz. Bir bildirim alana kadar uykuda kalır. Bir işletim sistemi iş parçacığını meşgul tutması dışında, tamamen oyun dışıdır.

Bu nedenle notifyAll'ı kullanmak idealden daha azdır, daha önce mutlu bir şekilde uykuda olan bir grup iş parçacığının uyanmasına neden olur, çoğu kilit elde edene kadar bloke eder, bulundukları durumu bulurlar. beklemek doğru değildir ve beklemeye geri dönün. Yalnızca ilerleme sağlama şansı olan konuların bildirilmesi tercih edilir.

(İçsel kilitler yerine ReentrantLock'u kullanmak, bir kilit için birden fazla koşula sahip olmanızı sağlar, böylece bildirilen iş parçacığının belirli bir koşulu bekleyen bir iş parçacığı olduğundan emin olabilirsiniz ve bir iş parçacığının bildirilmesi durumunda kayıp bildirim hatasını önleyebilirsiniz. üzerinde hareket edemeyeceği bir şey.)


Bunun nedeni, monitör nesnesinde notify () işlevini çağırmanın başka bir iş parçacığı sorumluluğu olduğu için mi?
berimbolo

@berimbolo: Ne sorduğunu anlamıyorum
Nathan Hughes

Bekleyen iş parçacığının neden zamanlayıcının endişelenmesi gereken bir şey olmadığı ile ilgiliydi. Merak ettim, çünkü başka bir iş parçacığı bekliyorsa bildirim çağırmaktan sorumlu olacak.
berimbolo

@berimbolo: Bekleyen iş parçacığı, sonunda bir bildirim tarafından uyandırılır. Planlayıcı, hangi bekleyen iş parçacığının bildirileceğine karar verecektir.
Nathan Hughes

bir şeyi sayıyor, dönme kilidi diyorsunuz, ENGELLENMİŞ doz, bunun dönme kilidi olduğu anlamına gelmez
Frank Zhang

16

İş parçacığı dökümlerini yorumlamak için basitleştirilmiş perspektif:

  • BEKLE - Biraz iş verilmesini bekliyorum, bu yüzden şu anda boştayım.
  • ENGELLENDİ - İşi halletmekle meşgulüm ama yolumda başka bir konu duruyor, bu yüzden şu anda boştayım.
  • ÇALIŞTIRILABİLİR ... (Yerel Yöntem) - JVM söz konusu olduğunda bazı yerel kodları ÇALIŞTIRMAK için çağırdım (henüz bitmedi), ÇALIŞTIRILABİLİRSİNİZ ve daha fazla bilgi veremez. Yaygın bir örnek, aslında herhangi bir trafiğin gelmesini bekleyen, C kodlu yerel bir yuva dinleyici yöntemi olabilir, bu nedenle şu anda boştayım. Bu durumda, aslında ÇALIŞMIYORUZ (CPU yakma yok), ancak bunu görmek için bir Java iş parçacığı dökümü yerine bir işletim sistemi iş parçacığı dökümü kullanmanız gerekeceğinden, bu özel bir BEKLEME türü olarak görülebilir.

1
Açıklamanı beğendim. Şu anda iş parçacığı dökümlerini analiz ederken yapmaya çalıştığım şey tam olarak bu :)
Sridhar Sarnobat

@MuhammadGelbana Evet, haklısın, yorumu sildim.
Eric Wang

1
Pek RUNNABLEdoğru değilsin. Java çalıştırma kuyruğunda olabilir, ancak yürütülmüyor olabilir veya Java kodunu çalıştırıyor olabilir. Yerli topraklara seslenmek zorunda değil.
Gray

1

Engellendi - İş parçacığınız, iş parçacığı yaşam döngüsünün çalıştırılabilir durumunda ve nesne kilidi elde etmeye çalışıyor. Bekle - İş parçacığınız iş parçacığı yaşam döngüsünün bekleme durumunda ve iş parçacığının çalıştırılabilir durumuna gelmesini bildirme sinyalini bekliyor.


-1

bu örneğe bakın:

iş parçacığı durumlarının gösterimi.

/*NEW- thread object created, but not started.
RUNNABLE- thread is executing.
BLOCKED- waiting for monitor after calling wait() method.
WAITING- when wait() if called & waiting for notify() to be called.
  Also when join() is called.
TIMED_WAITING- when below methods are called:
 Thread.sleep
 Object.wait with timeout
 Thread.join with timeout
TERMINATED- thread returned from run() method.*/
public class ThreadBlockingState{

public static void main(String[] args) throws InterruptedException {
    Object obj= new Object();
    Object obj2 = new Object();
    Thread3 t3 = new Thread3(obj,obj2);
    Thread.sleep(1000);
    System.out.println("nm:"+t3.getName()+",state:"+t3.getState().toString()+
            ",when Wait() is called & waiting for notify() to be called.");
    Thread4 t4 = new Thread4(obj,obj2);
    Thread.sleep(3000);
    System.out.println("nm:"+t3.getName()+",state:"+t3.getState().toString()+",After calling Wait() & waiting for monitor of obj2.");
    System.out.println("nm:"+t4.getName()+",state:"+t4.getState().toString()+",when sleep() is called.");
}

}
class Thread3 extends Thread{
Object obj,obj2;
int cnt;
Thread3(Object obj,Object obj2){
    this.obj = obj;
    this.obj2 = obj2;
    this.start();
}

@Override
public void run() {
    super.run();
    synchronized (obj) {
        try {
            System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",Before Wait().");
            obj.wait();             
            System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",After Wait().");
            synchronized (obj2) {
                cnt++;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
}
class Thread4 extends Thread{
Object obj,obj2;
Thread4(Object obj,Object obj2){
    this.obj = obj;
    this.obj2 = obj2;
    this.start();
}

@Override
public void run() {
    super.run();
    synchronized (obj) {
        System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",Before notify().");
        obj.notify();
        System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",After notify().");
    }
    synchronized (obj2) {
        try {
            Thread.sleep(15000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
}

Kod için teşekkürler, ancak metinsel bir cevabınız olmasını ve ardından küçük bir kod bloğu göstermenizi tercih ederim .
Gray
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.