KABAFORCEGeliştirici KabaOS'u edinin
Önizleme · 0.6.0 — dil 1.0 öncesidir; sözdizimi ve kütüphane değişebilir. Buradaki her örnek derlenerek sınanır.

7. Eşzamanlılık — birlikte, baslat, kanal

Aynı anda birden çok iş yapmak. KabaLang'in modeli yapılandırılmış eşzamanlılıktır: görevler bir kapsamda doğar ve o kapsam bitmeden hepsi biter. Böylece "arka planda unutulmuş görev" diye bir şey olmaz.

birlikte: + baslat

KabaLang
fonksiyon is_yap(ad):
    yazdir("çalışıyor: " + ad)

birlikte:
    baslat is_yap("a")
    baslat is_yap("b")
    baslat is_yap("c")

yazdir("hepsi bitti")

birlikte: bloğu, içindeki bütün görevler bitmeden bir sonraki satıra geçmez. Yukarıdaki programda hepsi bitti her zaman en sonda yazılır.

Görevden değer almak — baslat + bekle()

KabaLang
fonksiyon kare(x):
    don x * x

birlikte:
    a = baslat kare(6)
    b = baslat kare(7)
    dogrula(a.bekle() == 36, "a")
    dogrula(b.bekle() == 49, "b")

yazdir("görev değerleri tamam")

⚠️ g = baslat f() yalnız bir birlikte: bloğunun içinde yazılabilir. Blok dışında yazarsanız derleyici hata[KAPSAMSIZ_BASLAT] verir (kabalang acikla KAPSAMSIZ_BASLAT) — çünkü görev tutamacı kapsamın kendisine bağlıdır:

Derlenmez
fonksiyon kare(x):
    don x * x

g = baslat kare(6)
yazdir(metin(g.bekle()))

arkada_calistir: — kapsamsız arka plan işi

Beklemek istemediğiniz kısa işler için:

KabaLang
kullan kaba.sistem

fonksiyon selam():
    yazdir("arka planda")

arkada_calistir:
    selam()

uyu(300)                 # işin görünmesi için bekliyoruz
yazdir("ana akış sürdü")

⚠️ arkada_calistir yerel değişken YAKALAYAMAZ. Yakalarsa derleme KACAK_YAKALAMA ile durur — uyarı değil, hata. Sebep: yerel değişken görev bitmeden yok olabilir; bu, sessiz bir bellek hatası olurdu.

Derlenmez
fonksiyon f():
    v = "yerel"
    arkada_calistir:
        yazdir(v)

f()

Derleyicinin önerdiği çözüm gerçekten çalışır — görevi birlikte: kapsamına alın; kapsam bitmeden görev biteceği için yakalama güvenlidir:

KabaLang
fonksiyon f():
    v = "yerel"
    birlikte:
        baslat yazdir(v)

f()
yazdir("güvenli yakalama")

kanal<T> — görevler arası veri

Kanal, bir görevin ürettiğini başka bir görevin tüketmesini sağlar. Kilit yazmanız gerekmez.

KabaLang
fonksiyon uret(kn):
    dongu i icinde 1..5:
        kn.gonder(i)
    kn.kapat()                      # ⚠️ kapatmazsanız tüketici sonsuza kadar bekler

fonksiyon tuket(kn):
    toplam = 0
    iken dogru:
        v = kn.al()
        eger v.bos_mu():            # kanal kapandı
            kir
        toplam = toplam + v.deger()
    dogrula(toplam == 15, "1..5 toplamı")
    yazdir(f"toplam: {toplam}")

k: kanal<sayi> = kanal(2)           # 2 elemanlık tampon
birlikte:
    baslat uret(k)
    baslat tuket(k)

yazdir("kanal tamam")
Yazım Anlamı
kanal(n) n elemanlık sınırlı tampon; dolunca gönderen bekler (geri basınç)
kanal(0) randevu: gönderen, alıcı teslim alana kadar bekler
kn.gonder(v) veri koy
kn.al() veri al — belki<T> döner; bos kanalın kapandığını gösterir
kn.kapat() artık veri gelmeyecek

Randevu (tamponsuz) kanal:

KabaLang
fonksiyon uret(kn):
    dongu i icinde 1..3:
        kn.gonder(i)
    kn.kapat()

fonksiyon tuket(kn):
    toplam = 0
    iken dogru:
        v = kn.al()
        eger v.bos_mu():
            kir
        toplam = toplam + v.deger()
    dogrula(toplam == 6, "randevu kanalı")

k: kanal<sayi> = kanal(0)
birlikte:
    baslat uret(k)
    baslat tuket(k)

yazdir("randevu tamam")

Birden çok üretici tek kanala yazabilir; hepsi bitmeden kanalı kapatan ayrı bir görev kullanılır:

KabaLang
kullan kaba.sistem

fonksiyon uret(kn, bas):
    dongu i icinde 1..3:
        kn.gonder(bas + i)

fonksiyon kapatici(kn):
    uyu(300)
    kn.kapat()

fonksiyon tuket(kn):
    toplam = 0
    iken dogru:
        v = kn.al()
        eger v.bos_mu():
            kir
        toplam = toplam + v.deger()
    dogrula(toplam == 42, f"1+2+3 + 11+12+13 = 42 bekleniyordu")
    yazdir(f"toplam: {toplam}")

k: kanal<sayi> = kanal(8)
birlikte:
    baslat uret(k, 0)
    baslat uret(k, 10)
    baslat tuket(k)
    baslat kapatici(k)

yazdir("çok üretici tamam")

Uyumak: uyu(ms)

KabaLang
kullan kaba.sistem

uyu(200)                      # 200 milisaniye
yazdir("uyandım")

⚠️ bekle adı görev beklemek için ayrılmıştır (g.bekle()); uyku için uyu(ms) yazın. Servis yazıyorsanız uyu() bile yanlış seçimdir: servis.uyu(ms) sinyal gelince anında uyanır (11. sayfa).

yazdir iş parçacığı güvenlidir

Birden çok görev aynı anda yazdir çağırabilir; satırlar iç içe geçmez. (Bu ölçülmüş bir kusurdu: düz cout kullanımıyla beş koşunun üçünde satırlar birbirine karışıyordu.)

Bugün olmayan

  • async anahtar sözcüğü rezerve edilmiştir ama uygulanmamıştır. Yazarsanız "henüz uygulanmadı" yanıtı alırsınız; eşzamanlılık bugün birlikte/baslat/kanal üzerinden yazılır.
  • Paylaşılan bir değişkeni iki görevden aynı anda yazmak yarış koşuludur; dil bunu bugün engellemez. Veri paylaşımını kanal ile yapın.

Sonraki adım

8. Standart kütüphane turu