GO RUNTIRE, goroutinler arasında verimli, adil ve kilitsiz iletişim sağlamak için veri yapılarının, kilitleme mekanizmalarının, goroutin planlamasının ve senkronizasyonun sofistike bir koordinasyonu yoluyla kanal işlemlerini dahili olarak işler.
Go'daki kanallar, öncelikle kanalın tamponu, bekleyen gönderenler ve alıcılar kuyrukları, senkronizasyon ilkelleri ve kanalın kapalı olup olmadığı gibi meta bilgilerini içeren kanalın durumunu kapsayan veri yapısı olarak uygulanır. Bir kanal oluşturulduğunda, yığın üzerine bir `` hchan '' tahsis edilir ve kanalı temsil eden değer bu yapıya işaret ederek birden fazla goroutinin aynı anda referans vermesine ve kullanmasına izin verir.
Özünde, bir kanal aşağıdakilerden oluşur:
- Bir dilim ve `sendx` ve` recvx '' ile temsil edilen tamponlu kanallar için dairesel bir tampon sırasıyla nereye gönderilecek ve alacağınızı hangi iz bırakır. Tampon boyutu kanal oluşturma üzerine sabitlenir ve gönderilen ancak henüz alınmayan öğeleri depolayan bir kuyruk görevi görür.
- Gönderme (`sendq`) ve alma (` recvq`) ile engellenen goroutinleri yönetmek için iki FIFO bekleme kuyruğu (bağlantılı listeler). Bu kuyruklar, gönderilecek değer veya bir değer alacağı nereye bir işaretçi gibi kanal işlemleri için engellenen goroutini ve ilgili verileri temsil eden `Sudog 'yapılarını depolar.
- Kanalın iç yapılarına eşzamanlı erişimi korumak için bir muteks kilidi, gönderme ve alım işlemlerinin tutarlılığı korumasını ve eşzamanlı erişim altında kanalın durumunu bozmamasını sağlar.
Kanal Gönder işlemi
Bir goroutine bir kanala (`ch e işlemi
Alma işlemi (`Lexity:
1. Kilit edinimi: Kanalın muteksi kilitli.
2. Bekleyen gönderenleri kontrol edin: `sendq '' de bekleyen bir gönderen varsa:
- Alıcı değeri doğrudan gönderenin `` sudog '' dan alır.
- Gönderen tanımlanır ve çalıştırılabilir olarak işaretlenir.
- Her iki goroutin de arabelleğe alınmadan hemen devam ediyor.
3. Tamponun arabelleğini kontrol edin: Gönderen beklemiyorsa:
- Kanal, arabelleğinin herhangi bir öğe içerip içermediğini kontrol eder.
- eğer öyleyse, bir öğe `buf [recvx]` tampon konumundan kopyalanır.
- `recvx 'dizinleri arttırılır ve` qcount' azaltılır.
- Kilit serbest bırakılır ve alıcı engellemeden devam eder.
4. Alıcıyı engelleme: arabellek boşsa ve gönderen beklemiyorsa:
- Alıcı goroutine `` sudog '' olarak temsil edilir.
- `recvq 'ile enqueed.
- Alıcı, bir gönderme işlemini engelleyene kadar zamanlayıcı tarafından park edilir.
5. Kapalı kanal alır: Kanal kapalıysa ve arabellek boşsa:
- Eleman türünün sıfır değerini döndürür.
- Alıcılar, alma işleminden dönen ikinci boole tarafından kapalı durumu engellemez ve tespit edebilir.
6. Adalet ve Düzen: Bekleyen alıcılar adaletini korumak için FIFO'ya tabi tutulur ve planlama, sipariş kısıtlamalarına saygı duyar, ancak zamanlama davranışı nedeniyle katı zamanlama sırasını garanti etmez.
Park ve Zamanlama Entegrasyonu
Kanallar, üç varlık kullanarak Goroutine Lifeccles'i yöneten Go'nun Goroutine Zamanlayıcısı ile sıkı bir şekilde entegre edilmiştir:
- G (goroutine): Hafif, kullanıcı düzeyinde iş parçacığı.
- M (Makine): Goroutines'i yürüten işletim sistemi.
- P (işlemci): GO kodunu yürütmek için gereken yerel bir çalıştırılabilir goroutin ve kaynak kuyruğunu tutar.
Bir kanal işlemi engellediğinde (gönder veya al), goroutine:
- Bekleme olarak işaretlenmiştir.
- Sahip olan `p`in yerel çalışma kuyruğundan kaldırılır.
- İlgili kanal kuyruğunda (`sendq` veya` recvq`) bir `sudog 'yapısı ile bağlanır.
- Zamanlayıcı daha sonra o `p` üzerinde çalıştırmak için başka bir çalıştırılabilir goroutin seçer.
Engellenen işlem tamamlanmaya hazır hale geldiğinde (örneğin, bir muadili gönderme veya alma olur):
- Bekleyen goroutine kanal kuyruğundan ayrılır.
- Runnable olarak işaretlendi.
- Zamanlama için yerel veya küresel bir çalıştırma kuyruğuna yerleştirin.
- Goroutine sonunda yürütmeye devam edecek.
Bu tasarım, yoğun beklemeyi önler ve geleneksel işletim sistemi iplik engellemesine kıyasla minimum genel giderle verimli bağlam değiştirme sağlar.
Kanal Kapatma işlemi
Bir kanalı kapatma, aynı muteks tarafından korunan `` hchan '' da `` kapalı '' bayrağı ayarlar. Bir kanalı kapatmak aşağıdakilere neden olur:
- Göndermeye çalışıyorsa tüm engellenen gönderenler paniğe kapılır.
- Engellenen tüm alıcılar, kalan tamponlu değerleri ve ardından sıfır değerleri almak için FIFO sırasıyla engellenir.
- Further receives return zero values immediately without blocking.
- Hemen kapalı kanal panikleri göndermek.
- Yakın işlem, yarış koşullarından kaçınmak için Mutex aracılığıyla kanal işlemleri ile senkronize edilir.
dahili veri yapıları
- hchan: merkezi yapı tutma:
- `Buf` (tampon dizi işaretçisi)
- `dataqsiz` (tampon boyutu)
- `qCount '(şu anda tamponlanmış öğelerin sayısı)
- `sendx`,` recvx` (tampon indeksleri)
- `sendq`,` recvq` (engellenen gönderenler ve alıcılar için bekleme sıraları)
- `kapalı 'bayrak
- Gömülü muteks (durumu korumak ve çoklu eşzamanlı işlemleri koordine etmek için).
- Sudog: Bir kanal işleminde bekleyen bir goroutini temsil eden dahili çalışma zamanı yapısı. Tutar:
- Goroutine'ye bir işaretçi.
- Gönderilen veya alınan verilere işaret edenler.
- Bekleme kuyruğunda bir sonraki `sudog 'ile bağlantılar.
- Waitq: Garsonları (`sendq`) veya garsonları (` recvq`) temsil eden bağlantılı sudoglar listesi. FIFO adaletini sağlamak.
SELECT deyimini ve kanalları seçin
GO'nun `Select` ifadesi karmaşıklığı getirir, çünkü birden çok kanal işlemi aynı anda rekabet eder. Çalışma zamanı, her bir Seçim Kılıfı için birden fazla bekleme kuyruğunu yönetir ve birden çok kanaldan çevrimdışı seçme şunları içerir:
- Her durumda bloke etmeyen işlemleri denemek.
- Hiçbiri devam ederse, tüm ilgili kuyruklarda goroutin'i enfe etmek.
- Bir operasyon devam edebildiğinde, diğer garsonlar çıkarılır ve goroutin engellerini kaldırır.
Bu seçici bekleme mekanizması, adalet ve verimliliği korumak için çalışma zamanı zamanlayıcı ile derinden entegre edilmiştir.
Performans ve Eşzamanlılık Hususları
Kanal tasarımı, güvenlik ve performans arasında denge için çabalar:
- Mutex Kilitleme: Tutarlılık sağlar, ancak çok yüksek tartışma altında bir darboğaz haline gelebilir. Çalışma zamanı, durumu atomik olarak güncellemek için kilidi kısaca tutar.
- Doğrudan Handoff: Goroutinler arasında daha hızlı iletişime izin vererek mümkün olduğunda tampon ek yükünü önler.
- Park ve Parklandırma: OS iş parçacıklarına kıyasla bağlam anahtarlama yükünü en aza indirir.
- Adalet: Açlığı önlemek için FIFO kuyrukları ile uygulanır.
- Önbellek ve yerellik: Parkmamış goroutinler farklı işlemcilerde (`p`s) devam edebilir ve muhtemelen önbellek kaçırmalarına yol açabilir.
- Gürleme Sürüsü Sorunu: Bir kanalı kapatma veya yayınlama aynı anda birçok goroutin'i uyandırabilir, bu da zamanlayıcı tarafından mantıklı bir şekilde ele alınmalıdır.
Kanallar, GOutin Zamanlama Mekanizmaları ile kilit korumalı bir halka tamponunu birleştiren, GO programlarında güvenlik, sipariş ve verimlilik sağlayan zarif bir eşzamanlılık ilkelini temsil eder.
GO kanalı işlemlerinin iç kısımları, veri yapıları, kilitleme ve çalışma zamanı zamanlayıcısı arasında sıkı bir bağlantı ortaya çıkarır, senkronizasyonu kullanıcı düzeyinde hafif iş parçacıklarına yerleştirir ve ağır işletim sistemi çekirdek etkileşimi olmadan zengin iletişim modellerini sağlar. Bu yaklaşım, Go'nun eşzamanlılık modelini farklılaştırır ve kanalların bir programcının bakış açısından hem etkili hem de kullanımı basit olmasının temel bir nedenidir.