Devlet makineleri


24

Alan Cox zamanlar söyledi "Bilgisayar bir durum motorudur. Konular olamayan programı durum makineleri insanlar içindir".
Alan'a doğrudan sormak alçakgönüllü bir seçenek olmadığından, burada sormayı tercih ederim: Bir kişi, yalnızca bir iş parçacığı ve durum makinesi kullanarak, Java gibi üst düzey bir dilde çoklu iş parçacığı işlevini nasıl elde eder? Örneğin, gerçekleştirilecek 2 etkinlik varsa (hesaplamalar yapıyor ve G / Ç yapıyorsa) ve bir etkinlik engelleyebiliyorsa ne olur?
"Yalnızca devlet makinesi" yönteminin kullanımı, üst düzey dillerde çoklu iş parçacılığına alternatif bir yöntem midir?


4
Bir bilgisayar aynı zamanda bir Turing makinesidir. Bununla birlikte, bir Turing makinesi gibi programlanması kesinlikle gerekli değildir. Zorunlu dillerdeki yığın, oldukça faydalı bir şeydir ve çok iş parçacıklı programlar, aynı anda birden fazla yığını bellekte tutmaya izin verir. Aynısını bir durum makinesinde yapmak elbette mümkün ama hepsi daha da dağınık.
thiton

10
Alan bir işletim sistemi çekirdek geliştiricisiydi; Bu onun domisi idi . Bu yüzden onun teklifi bu bağlamda alınmalıdır. Böyle bir modeli kullanmanın daha mantıklı olduğu 'metale karşı' programlama yapacaktı. İşletim sistemi donanımı soyutladığında ve onun kendine özgü özelliklerinde (“bilgisayar bir devlet makinesidir”) soyutladığında , etki alanınızda daha anlamlı olan diğer modelleri kullanabilme fırsatınız ve avantajınız olur . Neredeyse her oyun devlet makinelerini ağır kullanıyor.
Steven Evers

2
Threading basitçe, işletim sistemi durumundaki bazı anahtarlarınızı otomatik olarak yönetmeniz için bir özelliktir. Açıkçası her şeyi kendi başına yönetecek devasa bir devlet makinesi yaratabilirsiniz, ama bu daha karmaşık. Aynı işlemler hakkında söylenebilir. Süreçlerin devlet makinelerini de programlayamayan insanlar için olduğunu söyleyebilirsin. Ancak soyutlama size çok daha basit ve daha az hata eğilimli bir arayüz sunar. Bence bu, duyulması, tasarlanması ve gerçekte göz ardı edilmesi gereken başka bir "güzel alıntı" dır.
Yam Marcovic

2
“Ama [thread] soyutlaması size çok daha basit ve daha az hata eğilimli bir arayüz sunuyor.” Bu yanlış gibi görünüyor. İplik güvenliği yanlış olan kişilerin sayısı, hataya yol açtığını gösterir.
S.Lott

1
Buradaki birçok yorum ve cevap, alıntıyı genel olarak çoklu görev karşıtı olarak değerlendirmektedir; Alan Cox'un sadece konuların karşıtı olduğunu ve insanların konu kullandığı birçok hedefi başarmak için çoklu süreçleri kullanmayı savunacağına inanıyorum. Unix'in bir hacker olduğunu unutmayın: çatal FTW. Doğrudan alıntıyla ilgili herhangi bir yorum bulamadım, ancak işte bu yöndeki Linux çekirdeği posta listesinden Larry McVoy'dan biri
Martin B,

Yanıtlar:


25

Bir iş parçacığının yaptığı tek şey işlemleri birleştirmek, böylece işlemin bölümlerinin zamanla çakışmış gibi görünmesidir. Birden fazla ipliğe sahip tek çekirdekli bir makine sadece etrafta zıplar: bir ipliğin küçük kod parçalarını yürütür, sonra başka bir ipliğe geçer. Basit bir zamanlayıcı, hangi iş parçacığının en yüksek öncelik olduğuna ve gerçekte çekirdeğin içinde yürütüldüğüne karar verir.

Tek çekirdekli bir bilgisayarda, aslında "aynı anda" hiçbir şey olmuyor. Hepsi sadece serpiştirilmiş infaz.

Araya eklemeyi başarmanın pek çok yolu var. Birçok.

Her iki iş parçacığının ortak bir değişkene yazabilmesi için basit bir kilit kullanan basit bir iki iş parçacıklı işleminiz olduğunu varsayalım. Altı kod bloğunuz var.

  • T1 öncesi kilit
  • T1 kilidi
  • T1 sonrası kilit
  • T2 öncesi kilit
  • T2 kilidi
  • T2 sonrası kilit

[Bu bir döngüde olabilir veya daha fazla kilit veya her neyse olabilir. Tek yaptığı daha uzun, daha karmaşık değil.

T1'in adımları sırayla çalışmalıdır (T1 öncesi, T1 ile, T1 sonrası) ve T2'nin adımları sırayla (T2 öncesi, T2 ile, T2 sonrası) gerçekleştirilmelidir.

"Sıralı" kısıtlama dışında, bunlar herhangi bir şekilde araya sokulabilir. Herhangi bir şekilde. Yukarıda listelendiği gibi çalıştırılabilirler. Başka bir geçerli sipariş (T1 öncesi, T2 öncesi, T2 kilidi, T1 kilidi, T2 sonrası, T1 sonrası). Çok fazla geçerli sipariş var.

Bekleyin.

Bu sadece altı eyalete sahip bir devlet makinesidir.

Belirleyici olmayan bir sonlu durum otomatı. T1-xxx durumlarının T2-xxx durumlarıyla sıralanması belirsizdir ve önemli değildir. Bu yüzden, "sonraki devlet" in bozuk para attığı yerler var.

Örneğin, FSM başladığında, T1-öncesi ya da T2-öncesi her ikisi de meşru ilk durumlardır. Bozuk para atmak.

Diyelim ki T1'den önce geldi. Yap bunu. Bu yapıldığında, T1-ile T2-öncesi arasında bir seçim var. Bozuk para atmak.

FSM'deki her adımda iki seçenek (iki iplik - iki seçenek) olacak ve bir bozuk para atışı hangi özel durumun izleneceğini belirleyecektir.


Teşekkürler, güzel açıklama. Peki ya çok çekirdekli makine? Sanırım, Java eyalet makinesinde çekirdeklerden yararlanmanın kesin bir yolu yok mu? Bunun için OS'ye güvenilmesi gerekiyor, değil mi?
Victor Sorokin 23:11

5
Çok çekirdekli bir makine zamanlamayı biraz daha karmaşık hale getirir. Ancak, tüm çekirdekler tek bir ortak belleğe yazılır, bu nedenle iki çekirdek arasındaki Bellek Yazma Sırası, esasen - bellek yazma işleminin harmanlanmasına geri döndüğümüz anlamına gelir. İşletim sistemi çekirdeklerden yararlanıyor ve JVM bunu kullanıyor. Bunun hakkında iki kez düşünmenize gerek yok.
S.Lott

9

Engelleme işlevlerini yazmak, devlet makineleri oluşturamayan insanlar içindir;)

Engellemeyi engelleyemezseniz, iş parçacığı kullanışlıdır. Hiçbir temel bilgisayar etkinliği gerçekten engellemediğinden, kullanım kolaylığı için çoğu bu şekilde uygulanır. Bir karakter döndürmek veya "başarısız okuma" yerine, okuma işlevi tüm tampon okunana kadar engeller. Sıradaki dönüş iletisini denetlemek ve hiçbiri bulunamazsa döndürmek yerine, connect işlevi yanıt bekler.

Bir durum makinesinde engelleme işlevlerini kullanamazsınız (en az bir tanesi "dondurmasına" izin verilemez).

Ve evet, durum makinesini kullanmak uygun bir alternatiftir. Gerçek Zamanlı sistemlerde, makine için bir çerçeve sağlayan sistem tek seçenektir. İpliklerin kullanılması ve engelleme işlevlerinin kullanılması sadece "kolay yoldur", çünkü genellikle engelleme işlevine yapılan bir çağrı durum makinesinde yaklaşık 3-4 durumun yerini almaktadır.


Tek bir yürütme bağlamındaki programdaki bir kod sayfası hatası temelde gerçekten engelliyor. Tanım olarak, tek bir yürütme bağlamına sahip olan kod, akıştaki bir sonraki kod öbeği mevcut olana kadar ileriye doğru ilerleyemez.
David Schwartz

1
@David Schwartz: Doğru, temelde engelliyor; fakat bu bir 'işlem' değildir, çünkü engellenen kodun yaptığı bir şey değildir, ona olan bir şeydir.
Javier,

1
Dosya okuma temelde engelleme yapmaz - verilen konumun okunmasını istemek ve istek yerine getirildikten sonra verileri tamponlardan almak her zaman ayrılabilir. Sayfa hatası, tesadüfi / sezgisel takas kullanımı için geçici bir çözümdür. Eğer belirtilen duruma, yürütülmesi için gerekli olan tüm veriler sunulmadan önce girilirse ortaya çıkar - öngörü eksikliği, devlet makinesi kavramına karşı bir şey. Değiştirme ve değiştirme işlemleri durum makinesinin bir parçasıysa, bir sayfa hatası oluşmaz.
SF.

1
@David Schwartz: "Engelleme" davranışının tanımı her zaman "gerçek zamanlı" şartlara tabidir. Örneğin: Kod sayfası hatası, yüzlerce milisaniye sırasına göre yanıt verebilirlik gerektiren uygulamalarda engellenmez olarak kabul edilir. Öte yandan, uygulamanın katı gerçek zamanlı gereksinimleri varsa, hiçbir zaman sanal belleği kullanmaz.
11:11

1
@Mar: ... ya da gerekli olmadan önce gerekli verilerin alınmasını garanti eden deterministik bir takas algoritması kullan.
SF.

9

Kişi tek bir iş parçacığı ve durum makinesi kullanarak, Java gibi üst düzey bir dilde çoklu iş parçacığı işlevselliğini nasıl elde eder? Örneğin, gerçekleştirilecek 2 etkinlik varsa (hesaplamalar yapıyor ve G / Ç yapıyorsa) ve bir etkinlik engelleyebiliyorsa ne olur?

Anlattığınız şeye , işlemlerin CPU'ya verildiği ve belirli bir zaman veya faaliyet miktarından sonra gönüllü olarak bırakması beklenen kooperatif çoklu görev adı verilir. İşlemciyi kullanmaya devam ederek ya da tüm işleri engelleyerek ve bir donanım izleme zamanlayıcısına sahip olmaktan kaçınan, işbirliği yapmayan bir görev, görevleri denetleyen kodun yapabileceği hiçbir şey yoktur.

Modern sistemlerde gördüğünüze, preemptive multitasking adı verilir ; bu, görevlerin CPU'dan vazgeçmek zorunda kalmayacağı, çünkü süpervizör, donanım tarafından üretilen bir kesinti geldiğinde onlar için yapar. Süpervizördeki kesme servis rutini, CPU'nun durumunu kurtarır ve bir sonraki dilimin görevi bir zaman dilimini hakettiği kabul edildiğinde geri yükler, ardından bir sonraki çalıştırılacak olan şeyden durumu geri yükler ve hiçbir şey olmamış gibi tekrar atlar. . Bu eyleme bağlam anahtarı denir ve pahalı olabilir.

"Sadece devlet makinesi" yönteminin kullanılması, yüksek seviyeli dillerde çoklu iş parçacılığına alternatif bir yöntem midir?

Mantıklı mı? Emin. Aklı başında? Ara sıra. İş parçacığı kullanmanız veya bir tür ev yapımı kooperatif çoklu görev (örn. Devlet makineleri) kullanmanız, yapmak istediğiniz travmalara bağlıdır.

Konular, her birini veri alanını başkalarıyla paylaşan kendi programları olarak değerlendirebileceğiniz noktaya göre görev tasarımını basitleştirir. Bu, eldeki işe odaklanma özgürlüğünü verir ve her seferinde bir yineleme çalışması için gereken tüm yönetim ve temizlik işlerini yapmaz. Ancak hiçbir iyilik cezasız kalmayacağından, bağlam anahtarlarında tüm bu kolaylıkları ödersiniz. Minimal iş yaptıktan sonra (gönüllü olarak veya G / Ç gibi engelleyebilecek bir şey yaparak) CPU'yu veren birçok iş parçacığı olması bağlam geçişi yaparken çok fazla işlemci zamanı tüketebilir. Bu, özellikle eğer blokaj işlemleriniz çok nadiren bloke olursa geçerlidir.

İşbirliği rotasının daha anlamlı olduğu bazı durumlar vardır. Bir keresinde, yoklama gerektiren bellek eşlemeli bir arabirim aracılığıyla birçok veri kanalını aktaran bir donanım için bazı kullanıcı yazılımları yazmak zorunda kaldım. Her kanal, iş parçacığı olarak çalışmasına izin verebilecek veya tek bir yoklama döngüsünü art arda yürütebilecek şekilde inşa edilmiş bir nesneydi.

Çok okuyuculu sürümün performansı, tam olarak yukarıda ana hatlarıyla açıkladığım sebepten dolayı hiç de iyi değildi: her iş parçacığı minimum iş yapıyordu ve sonra CPU'yu diğer kanalların biraz zaman alabilmesi için bağlamsal anahtarlara dönüştürüyordu. Önceden işlenene kadar iş parçacıklarının serbest çalışmasına izin vermek, ancak donanıma bir arabellek taşması yaşanmadan önce bazı kanallara servis yapılmamasına neden oldu, çünkü bunlar yakında bir zaman dilimi alamadılar.

Her kanalın yinelemesini bile yapan tek dişli versiyon, haşlanmış bir maymun gibi koştu ve sistem üzerindeki yük bir kaya gibi düştü. Ek performans için ödediğim ceza, görevleri kendim yapmak zorunda kalmaktı. Bu durumda, yapılacak kod, geliştirme ve sürdürme maliyetinin performans iyileştirmeye değeceği kadar basitti. Sanırım bu gerçekten çok önemli. Konularım bazı sistem çağrısının geri dönmesini beklerken oturanlar olsaydı, alıştırma muhtemelen buna değmezdi.

Bu beni Cox'un yorumuna götürür: iplikler sadece devlet makineleri yazamayan insanlar için değildir . Bazı insanlar bunu yapabilme yeteneğine sahiptir ancak işin daha erken veya daha az karmaşık bir şekilde yapılması için bir konserve durum makinesi (örneğin bir iplik) kullanmayı tercih ederler.


2

gerçekleştirilecek 2 faaliyet varsa (hesaplamalar yapıyor ve G / Ç yapıyor) ve bir aktivite engelleyebiliyorsa ne olur?

Dürüst olmak gerekirse, engelleme giriş / çıkışını iş parçacığı olmadan nasıl kullanacağımı hayal edemiyorum. Buna sadece onu çağıran kodun olması gerektiği için engelleme denir wait.

Orijinal Cox’un e-postasını (aşağıdan) okuduğumda, diş açmanın iyi ölçeklenmemesine rağmen işaret ediyor. Yani, 100 G / Ç isteği varsa? 1000? 10000? Cox, çok sayıda dişe sahip olmanın ciddi sorunlara yol açabileceğini belirtiyor:

Gönderen: Alan Cox (alan@lxorguk.ukuu.org.uk)
Tarih: Cuma 21 Ocak 2000 - 13:33:52 EST

IBM makalesi), eğer uygulamanız çok fazla sayıda iş parçacığına bağlıysa, her zaman programlayıcıya karşı durmaya devam edersiniz. bir çok insan bir problemde birçok ip atıyor ve bu gerçekten kötü bir tasarım olabilir.

Endişelendiğin en az şey bu. 1000 iş parçacığı, 8 MB'lık çekirdek yığınlarıdır ve önbelleğinizin çoğunu da kapatabileceğinizden emin olmak için yeterli görev değişimi. Bir bilgisayar durum makinesidir. Konular program devlet makineleri yapamayan insanlar içindir.

Linux'un kesinlikle asenkron blok G / Ç durumuna yardım etmediği birçok durum vardır.

Alan

kaynak: Re: IBM'in linux çekirdeği iş parçacıklığının ilginç analizi (linux-çekirdek posta listesi arşivleri)


1
  • Teoride, bu doğru. Gerçek hayatta, dişliler böyle bir durum makinesini programlamak için kullanılan etkili bir soyutlamadır. O kadar verimlidirler ki, Statecharts ve Petri ağlarını da programlamak için kullanılabilirler (yani, durum makinelerinin temelde sıralı olduğu paralel davranışlar).

  • Devlet makinelerinde sorun, kombinasyonsal patlamadır. 4G RAM'li bir bilgisayarın durum sayısı 2 ^ (2 ^ 32) durumdur (2T disk sürücüsü sayılmaz).

  • Tek aleti çekiç olan bir adama, her problem bir çiviye benziyor.


1

İki durumda tek seçenek ipler:

  • hafıza ayırmadan çoklu çekirdek kullanmak için.
  • engelleyen harici kodla baş etmek için.

İkincisi, çoğu insanın iş parçacığının IO veya ağ programlaması yapmak için kaçınılmaz olduğunu düşünmesinin nedenidir, ancak bunun nedeni genellikle işletim sistemlerinin daha gelişmiş bir API'ye sahip olduğunu bilmemeleri (ya da bununla mücadele etmek istememeleridir).

Kullanım kolaylığı ve okunabilirlik söz konusu olduğunda, bir durum makinesini programlamayı neredeyse iş parçacığıyla yapmak kadar basit hale getiren, ancak eşitleme problemlerini unutmak için yeterli kontrolü sağlayan olay döngüleri ( libev veya EventMachine gibi) her zaman vardır .


1
Her iki dünyanın da en iyisi: Küçük, dişlilerin tıkanması durumunda durum makineleri, çok basit bir uygulama kodu oluşturur. Ve iplikler varsa, çekirdeğe güzelce ayrılır. Her şeyin en az iki çekirdeği yoksa, yakında olacak. yani dört çekirdekli kol tabanlı telefonlar 2012 geliyor.
Tim Williscroft

0

Durum makineleri ve çok okuyucunun etkileşime girme yöntemini geliştirmek için iyi bir yol GUI olay işleyicilerini incelemektir. Pek çok GUI uygulaması / çerçevesi, olası girdi kaynaklarını yok edecek ve alınan her girdi için bir işlev çağıracak tek bir GUI iş parçacığını kullanır; aslında, bu büyük bir anahtar olarak yazılabilir:

while (true) {
    switch (event) {
        case ButtonPressed:
        ...
        case MachineIsBurning:
        ....
    }
}

Şimdi, bu yapıdaki yüksek seviye kontrol seviyesinin yüksek olamayacağı oldukça hızlı bir şekilde ortaya çıkıyor: ButtonPressed'ın işleyicisi kullanıcı etkileşimi olmadan bitmeli ve ana döngüye geri dönmelidir, çünkü yapmazsa, başka kullanıcı etkinliği olmaz işlenebilir. Kaydedilecek bir durumu varsa, bu durumun genel veya statik değişkenlerde kaydedilmesi gerekir, ancak yığında değil; yani, zorunlu bir dilde normal kontrol akışı sınırlıdır. Aslında bir devlet makinesi ile sınırlandırılmışsınız.

Örneğin bir yineleme düzeyi kaydetmek zorunda olan iç içe geçmiş rutinleriniz olduğunda bu durum oldukça karışık olabilir. Ya da bir dosyayı okuma ortasında, ancak şu anda dosya kullanılamıyor. Ya da sadece uzun bir hesaplamada. Tüm bu durumlarda, mevcut uygulamanın durumunu korumak ve ana döngüye geri dönmek arzu edilir hale gelir ve bu çok okuyucudur . Ne fazla ne eksik.

Her şey, preemptive multithreading'in (yani, dişlilerin ne zaman kontrol edeceği konusunda karar veren işletim sistemi) ortaya çıkmasıyla biraz daha sarsıldı ve bu nedenle bağlantının bugün açık bir şekilde netleşmemesinin nedeni budur.

Böylece, son soruyu cevaplamak için: Evet, durum makinesi bir alternatif, çoğu GUI GUI iş parçacığı ile bu şekilde çalışır. Sadece devlet makinesini çok fazla ittirmeyin, çok çabuk anlaşılmaz hale gelir.


0

Bir durum makinesinin kullanılmasının yüksek seviyede bir dilde uygulanabilir olup olmadığını sormak, assembler'da yazmanın, yüksek düzeyde bir dil kullanmak için uygun bir alternatif olup olmadığını sormak gibidir. Her ikisi de doğru durum göz önüne alındığında kendi yerlerine sahip.

Iş parçacığı kullanmanın soyutlanması daha karmaşık paralel sistemlerin uygulanmasını kolaylaştırır, ancak sonuçta tüm paralel sistemlerin ele alınması gereken aynı sorunları vardır. Deadlock / Livelock ve öncelikli inversiyon gibi klasik problemler , durum makine kompleksi sistemlerinde, paylaşılan bellek paralelinde , NUMA'da ve hatta CSP tabanlı sistemde olduğu gibi, eğer karmaşıksa bile mümkün.


0

Bence devlet makineleri çok 'zarif' bir bilgi işlem konseptidir ancak dediğiniz gibi oldukça karmaşıklar. Ve karmaşık şeyleri düzeltmek zordur. Ve doğru olmayan şeyler kırıldı, bu yüzden Alan Cox'un varsayılan boyunun bir dehası olmadıkça, bildiğiniz şeylere bağlı kalmayın - 'akıllı kodlamayı' öğrenme projelerine bırakın.

Birisi boşuna bir girişimde bulunduğunda, (iyi çalıştığını varsayarsak), sürdürmek için geldiğinde, görevin imkansız olduğunu görürsünüz. Orijinal 'dahi', zorlukla anlaşılabilir bir kod öbeğiyle sizi terk etmeye devam edecektir (çünkü bu tür geliştiriciler, teknik belgelere rağmen çok fazla yorum bırakma eğiliminde değildir).

Bazı durumlarda, bir durum makinesi daha iyi bir seçim olacaktır - Ben şimdi bazı durum makinesi modellerinin kullanıldığı ve tekrar tekrar ve daha resmi bir şekilde kullanılan (yani uygun mühendislik :)) gömülü tip şeyler düşünüyorum

Diş açmanın da doğru yapılması zor olabilir, ancak asıl olarak dişler arasında veri paylaşma ihtiyacını azaltarak size yardımcı olacak modeller vardır.

Bununla ilgili son nokta, modern bilgisayarların zaten birçok çekirdek üzerinde çalışmasıdır, bu nedenle bir devlet makinesi mevcut kaynaklardan gerçekten iyi bir şekilde faydalanamayacaktır. Diş çekme burada daha iyi bir iş yapabilir.


2
Devlet makineleri hiç de karmaşık değil! Karmaşık durum makineleri karmaşık, ancak hepsi de karmaşık sistemler: o)
MaR

2
"Deneme" için -1. Verebileceğin en kötü tavsiye bu.
Javier,

1
-1 "Deneme"? Bu sadece aptalca. Ayrıca, devlet makinalarının zor olduğu iddiasına meydan okurdum. Bir Heirarchal Bulanık Devlet Makinesi gibi bir şeye girdiğinde ... o zaman evet, biraz daha karışık. Ama basit bir durum makinesi? Her 2 yılda bir okuldayken öğrendiğim çok basit şeyler.
Steven Evers


0

Konu yerine uygun durum makinesi kullanımına iyi bir örnek: nginx vs apache2. Genel olarak, nginx'in tek bir dizideki tüm bağlantıları işlediğini varsayabilirsin, apache2 bağlantı başına bir iplik yapar.

Ama benim için devlet makinelerini vs ipler kullanmak oldukça el yapımı asm vs java'yı kullanarak oldukça benzerdir: inanılmaz sonuçlar elde edebilirsiniz, ancak çok fazla disipline sahip çok sayıda programcının çalışması, projeyi daha karmaşık hale getirmesi ve yalnızca bir sürü başka programcı var. Eğer hızlı bir web sunucusu yapmak isteyen sizseniz - durum makineleri ve async IO kullanın. Eğer projeyi yazıyorsanız (her yerde kullanılacak olan kütüphaneyi değil) - konuları kullanın.

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.