Sobes.tech
Middle

Τι είναι ο χρόνος εκτέλεσης (runtime) και πώς λειτουργεί ο προγραμματιστής (scheduler);

sobes.tech AI

Απάντηση από AI

Ο χρόνος εκτέλεσης (runtime) στο Go είναι το περιβάλλον στο οποίο εκτελούνται τα προγράμματα Go. Περιλαμβάνει:

  • Διαχείριση μνήμης: Ο συλλέκτης απορριμμάτων (garbage collector) διαχειρίζεται αυτόματα την κατανομή και απελευθέρωση μνήμης.
  • Χρονοπρογραμματιστής (scheduler): Διαχειρίζεται την εκτέλεση των goroutines σε νήματα του λειτουργικού συστήματος.
  • Κλήσεις συστήματος: Παρέχει μια διεπαφή για αλληλεπίδραση με το λειτουργικό σύστημα.
  • Primitive συγχρονισμού: Κανάλια, mutex και άλλα μηχανισμοί για τον συντονισμό των goroutines.

Ο χρονοπρογραμματιστής του Go υλοποιεί το μοντέλο M:N (πολλές goroutines σε πολλά νήματα του λειτουργικού συστήματος). Τα βασικά του συστατικά:

  • G (Goroutine): Ένα ελαφρύ νήμα εκτέλεσης, ουσιαστικά μια αφαίρεση πάνω σε μια λειτουργία.
  • M (Machine): Ένα νήμα του λειτουργικού συστήματος πάνω στο οποίο εκτελούνται τα προγράμματα Go.
  • P (Processor): Ένας λογικός επεξεργαστής που συνδέεται με ένα νήμα του λειτουργικού συστήματος. Διατηρεί μια τοπική ουρά runnable για τις goroutines.

Αρχή λειτουργίας του χρονοπρογραμματιστή:

  1. Οι goroutines (G) δημιουργούνται και προστίθενται σε μια παγκόσμια ή τοπική ουρά runnable.
  2. Τα νήματα του λειτουργικού συστήματος (M) συσχετίζονται με λογικούς επεξεργαστές (P). Ο αριθμός P είναι προεπιλεγμένα ίσος με τον αριθμό των πυρήνων CPU (GOMAXPROCS).
  3. Το P παίρνει μια goroutine από την τοπική του ουρά. Αν η τοπική ουρά είναι άδεια, το P προσπαθεί να "κλέψει" (steal) goroutines από την ουρά ενός άλλου P ή από την παγκόσμια ουρά.
  4. Το M εκτελεί τη goroutine.
  5. Όταν μια goroutine μπλοκάρει (π.χ., κατά την ανάγνωση από ένα κανάλι χωρίς δεδομένα ή κατά την εκτέλεση μιας κλήσης συστήματος), το M αποσυνδέεται από το P, και το P γίνεται διαθέσιμο για την εκτέλεση άλλης goroutine. Η μπλοκαρισμένη goroutine τίθεται σε αναμονή. Όταν αφαιρεθεί το μπλοκάρισμα, η goroutine γίνεται ξανά runnable και τοποθετείται πίσω στην ουρά.
  6. Αν το M μπλοκάρει σε μια κλήση συστήματος, δεν διατηρεί το P. Μπορεί να δημιουργηθεί ένα νέο M ή να χρησιμοποιηθεί ένα υπάρχον, ώστε το P να συνεχίσει την εκτέλεση άλλων goroutines.

Αυτή η προσέγγιση επιτρέπει την αποδοτική χρήση των πόρων του επεξεργαστή και την εύκολη κλιμάκωση των παράλληλων εργασιών, κρύβοντας την πολυπλοκότητα της διαχείρισης των νήματων του λειτουργικού συστήματος από τον προγραμματιστή.

// Παράδειγμα δημιουργίας μιας goroutine
func myFunc() {
	// Κώδικας goroutine
}

func main() {
	go myFunc() // Εκκίνηση της goroutine
	// Το κύριο πρόγραμμα συνεχίζει την εκτέλεση παράλληλα
}