2009-02-28 15 views

cevap

50

Bu ilginç bir soru. Eşzamanlı olmayan programlama, temel olarak tek bir iş parçacığı olan, yani bir "sürekli yürütme işleminin ardından" olan bir programlama paradigmasıdır.

Javascript bakın, bu nedenle bir web tarayıcısının ortamında bu dili tartışalım. Bir web tarayıcısı, her pencerede tek bir javascript çalıştırması iş parçacığı çalıştırır, olayları (onclick = "someFunction()") ve ağ bağlantılarını (örneğin xmlhttprequest çağrıları gibi) işler.

(012)

(Bu, yalnızca kavramların gösterilmesi için çalışmayan bir örnektir).

Her şeyi eşzamansız bir şekilde yapmak için, denetleyici iş parçacığı 'ana döngü' olarak bilinen bir şeye sahiptir. Bir ana döngü böyle tür görünür:

while (true) { 
    event = nextEvent(all_event_sources); 
    handler = findEventHandler(event); 
    handler(event); 
} 

bir 'meşgul döngü' olmadığına dikkat etmek önemlidir. Bu, faaliyetin gerçekleşmesini bekleyen uyku ipi gibidir. Etkinlik kullanıcıdan girilebilir (Fare Hareketi, Düğme Tıklaması, Yazma) veya ağ etkinliği olabilir (Sunucunun yanıtı).

findEventHandler() aralık etiketinin üzerinde onclick olayı bulacağını

yayılma tıkladığında, bir ButtonClicked olay yaratacağı
  1. Yani yukarıdaki örnekte

    , ve daha sonra bu işleyici olacağını olay ile çağrıldı.

  2. xmlhttp isteği oluşturulduğunda, all_event_sources olay kaynakları listesine eklenir.
  3. performRequest() işlevi döndükten sonra, mainloop bir yanıtı bekleyen nextEvent() adımında bekler. Bu noktada, ele alınan diğer olayların “engellenmesi” hiçbir şey yoktur.
  4. Veriler uzak sunucudan geliyor, nextEvent() öğesi ağ olayını döndürüyor, olay işleyicisinin onreadystatechange() yöntemi olduğu, bu yöntemin çağrıldığı ve bir uyarı() iletişim kuralı tetikleniyor.

Uyarı() 'nın bir engelleme iletişim kutusu olduğunu belirtmek gerekir. Bu diyalog açıkken, başka hiçbir etkinlik işlenemez. Web sayfalarının javascript modelinin bir eksantrikliği, bu sayfa bağlamında daha fazla yürütmeyi engelleyecek hazır bir yönteme sahibiz. Özellikle JavaScript hakkında

+0

cevabının cevabının bir düzeltmesini öneririm "Bu değersizdir" 'dan farklıdır, bu sizin niyetiniz olduğunu düşündüğüm noTing değerine sahiptir ". Sadece okuyucular için kafa karışıklığını önlemek için – MadMurf

+0

@MadMurf: Ben de fark ettim .... ve düzeltdim. – mpen

+0

>> Asenkron programlama, temel olarak tek dişli olan bir programlama paradigmasıdır << - Burada akılda kalmamaya çalışıyorum, fakat bu ifadenin nasıl doğru olduğunu göremiyorum. Eşzamansız programlama, tekil ve çoklu olarak tek başına bırakılan parçacıklar hakkında herhangi bir şey ima eder mi? – Lee

15

Javascript modeli tek iş parçacıklı dur. Eşzamansız bir çağrı, numaralı numaralı yeni bir ileti değil, ancak yeni bir iş parçacığıdır. Bir çekirdeğindeki kesintilere benzer.

Evet, tek bir iş parçacığıyla eşzamanlı olmayan çağrılara sahip olmak anlamlıdır. Bunun hakkında düşünmek için: Tek bir iş parçacığı içinde bir işlevi çağırdığınızda, geçerli yöntemin durumu bir yığına (yani, yerel değişkenlere) aktarılır. Alt program başlatılır ve sonuçta geri döner, bu sırada orijinal durum yığından çıkarılır.

Eşzamansız bir geri aramada, aynı şey gerçekleşir! Aradaki fark, alt programın bir alt yordamı çağırmak suretiyle değil, sistem tarafından çağrılmasıdır.

+1

>> Eşzamansız arama yeni bir konu değil << - Bunun yanıltıcı bir açıklama olduğunu düşünüyorum. JS'nin bir XHR isteğine yeni iş parçacıkları ile hizmet vermesini engelleyen hiçbir şeyin farkında değilim. Yeni bir iş parçacığının şartname tarafından garanti edilmediği veya önerilmediği anlamına geldiğini düşünüyorum, ancak kesinlikle sistem tarafından uygulanan şekilde olabilir. – Lee

4

Birçok GUI uygulamasında, bir async çağrısı (Java'nın invokeLater gibi) yalnızca Runnable nesnesini GUI iş parçacığı sırasına ekler. GUI iş parçacığı zaten oluşturuldu ve yeni bir iş parçacığı oluşturmuyor. Ancak asenkron bir sistem için vida dişleri kesinlikle gerekli değildir. Örneğin, soketlere bloke olmayan aramalar yapmak için select/poll/kqueue vb. Kullanan libevent'i alın, daha sonra kodunuz için geri aramaları tamamen iş parçacığı olmadan tetikler.

5

bazı notlar:

XMLHttpRequest s varsayılan olarak engellenmeyen vardır. İstek, temel ağ yığınına iletildikten hemen sonra send() yöntemi döndürülür. Sunucudan gelen bir yanıt, diğer mükemmel yanıtlar tarafından ele alındığı gibi geri dönüşünüzü olay döngüsüne çağırmayı planlayacaktır.

Bu, yeni bir iş parçacığı gerektirmez. Temel soket API'si, Java'daki java.nio.channels'a benzer şekilde seçilebilir.

Bu open() üçüncü parametre olarak false geçirilerek senkronXMLHttpRequest nesneler oluşturmak mümkündür. Bu, sunucudan bir yanıt alınana kadar send() yönteminin engellenmesine neden olur ve böylece olay döngüsünü ağ gecikme merhametine yerleştirir ve ağ zaman aşımına kadar tarayıcıyı potansiyel olarak asılı tutar. Bu bir Bad Thing ™.

Firefox 3.5, Worker sınıfı ile tanrıya çok dilli JavaScript'i tanıtacaktır. Arka plan kodu tamamen ayrı bir ortamda çalışır ve olay döngüsünde geri aramaları zamanlayarak tarayıcı penceresiyle iletişim kurar.

+0

"Sunucudan gelen bir yanıt, geridönüşümün olay döngüsünde çağrılmasını planlayacak", hangi/iş parçacığı olay döngüsünde bir olayı başlatır ve geri çağrının çağrılmasına neden olur? – Yiling

+1

@Yiling Olay, tarayıcıda dahili bir I/O iş parçacığı tarafından oluşturulur; JavaScript'i yürüten bir iş parçacığı değil. – Matthew

2

Hayır, ancak birden fazla iş parçacığı dahil edilecektir.

Eşzamansız bir çağrı, işi yapmak için başka bir iş parçacığı başlatabilir veya bir başka, zaten çalışmakta olan bir iş parçacığında bir sıraya ileti gönderebilir. Arayan devam eder ve aranan kişi mesajı işlediğinde geri çağırır.

Bu bağlamda eşzamanlı arama yapmak isterseniz, bir ileti göndermeniz ve geri çağrının aktif olarak gerçekleşmesini beklemeniz gerekir.

Özet olarak: Birden fazla iş parçacığı dahil edilecek, ancak mutlaka yeni bir iş parçacığı oluşturmayacaktır.

2

Javascript hakkında bilmiyorum, ancak örneğin Windows Forms dünyasında, birden çok iş parçacığı olmadan eşzamanlı olmayan çağrılar yapılabilir. Bunun Windows İleti Pompasının çalışmasıyla ilgili olması gerekiyor. Temel olarak, Windows Forms uygulaması, Windows'un olayları bildiren iletileri yerleştirdiği bir ileti kuyruğu oluşturur. Örneğin, fareyi hareket ettirirseniz, mesajlar sıraya yerleştirilir. Windows Forms uygulaması, atılan tüm mesajları tüketen sonsuz bir döngüde olacaktır. Her mesajın içeriğine göre, pencereleri hareket ettirecek, diğer şeylerin yanı sıra onları yeniden çizecek, hatta kullanıcı tanımlı yöntemleri de başlatacaktır. Yöntemlere yapılan çağrılar delegeler tarafından belirlenir. Uygulama kuyrukta bir temsilci örneği bulduğunda, temsilci tarafından yönlendirilen yöntemi mutlu bir şekilde çağırır.

Eğer bir yöntem yapıyorsanız ve yeni bir iş parçacığı oluşturmadan bazı asenkronize işlerde çalışmak istiyorsanız, yapmanız gereken tek şey Control.BeginInvoke yöntemini kullanarak bir temsilci örneğini sıraya yerleştirmektir. Şimdi, bu aslında çok iş parçacıklı değil, ama kuyruğa çok küçük iş parçaları atarsanız, çok iş parçacıklı gibi görünecektir. Öte yandan, bunu yürütmek için zaman alıcı bir yöntem verirseniz, uygulama, bir şey yapsa bile, sıkışmış bir uygulama gibi görünecek şekilde, yöntem bitinceye kadar donacaktır.

İlgili konular