Zifnab wrote:
Η βασική μου απορία που ακόμα με βασανίζει είναι η διαφορά ανάμεσα σε ένα program μία process και ένα thread...
Ένα πρόγραμμα μπορεί να αποτελείται από πολλά processes και κάθε process από πολλά threads ή το έχασα?
Λοιπόν θα προσπαθήσω να το ξεκαθαρίσω, εάν κατάλαβα καλά τι ρωτάς.
1)Το
program είναι το αποτέλεσμα του
compilation. Ένα σύνολο απο εκτελέσιμες εντολές
packaged σε ένα συγκεκριμένο
executable format (.exe για win, elf για linux, a.out για παλιότερα unix και .class για java).
2)Tο
process χαρακτηρίζει κάθε
αυτόδύναμη εκτελέσιμη οντότητα που ζεί (γεννιέται,λειτουργεί και πεθαίνει) στο λειτουργικό. Κάθε ξεχωριστό program που εκτελείς είναι ένα process. Το ίδιο το process
απο μόνο του μπορεί να ξεκινήσει άλλα processes. Για παράδειγμα στο Unix το πρώτο program που εκτελείται είναι το init (αυτό στην συνέχεια ξεκινάει όλα τα υπόλοιπα) και φυσικά είναι και το πρώτο process. Τα processes χαρακτηρίζονται απο το
process id (pid) και συνεπώς το init έχει pid = 1. Κάθε process όπως σου είπα και παραπάνω μπορεί να κάνει spawn (να γενήσει κατα κάποιο τρόπο - αυτό αναφέρεται και σαν
fork σε unix περιβάλλοντα) και άλλα processes (με pids 2,3,4...). Όλα τα ενεργά processes τρέχουν
ταυτόχρονα* στο PC σου. Κάθε ξεχωριστό process έχει το δικό του
code space στην μνήμη (δηλαδή τον χώρο που υπάρχει ο εκτελέσιμος κώδικας του), το δικό
stack (για τις ενεργοποιήσεις των συναρτήσεων/μεθόδων) και το δικό του
heap (για να δεσμεύει δυναμικά μνήμη). Εάν τώρα ένα process γεννήσει πολλές φορές τον εαυτό του, να φτιάξει δηλαδή πολλά child processes (πχ πρόκειται για έναν παράλληλο αλγόριθμο που φτιάχνει πολλά instances για να επεξεργαστεί κάθε παράλληλο κομμάτι ένα υποσύνολο του input του) τότε κάθε ένα απο αυτά τα child process για να τρέξει ξεχωριστά απαιτεί απλά δικό του stack αλλά και heap (για να έχουν διαφορετικά data οι τοπικές μεταβλητές και να μπορεί να δουλέψει η παραλληλία). Μαζί με αυτά (heap και stack) θα αντιγράφεται στην μνήμη για κάθε child process και το code part, παρά το γεγονός ότι παραμένει το ίδιο**.
*)Εάν έχεις μία CPU τρέχουν παράλληλα αλλιώς ψευδοπαράλληλα.
**)Το κομμάτι εντολών δεν μπορεί να αλλάξει σε κανένα OS για λόγους ασφαλείας. Εαν έτσι απλά άλλαζαν τo executable part ενός προγράμματος τότε τα virusses θα ήταν trivial στο να γραφτούν.
3)To
thread είναι εντελώς διαφορετική ένοια απο το process. Εάν το δούμε απο πολύ ψηλά (αφηρημένα) είναι στην ουσία ένας πιο light τρόπος για να παραλληλήζεις κώδικα. Αρχικά όπως και στην παραπάνω περίπτωση θα υπάρχει ένα process το οποίο θα γεννήσει πολλά threads. Τα threads όμως δεν είναι ξεχωριστά processes (δεν αποκτά το καθένα απο αυτά ξεχωριστό pid και δεν έχει το καθένα δικό του heap, stack και code parts). Συνεπώς πολύ εύκολα (αφού δεν αντιγράφεις κομμάτια στην μνήμη) μπορείς να παραλληλίσεις τον κώδικα σου. Απο την άλλη ο προγραμματισμός είναι πολυπλοκότερος μιας και η χρήση
atomic εντολών αλλά και
locks είναι επιβεβλημένη. Αυτό είναι γιατί τα threads τεχνικά είναι πολλαπλές ροές εκτέλεσης οι οποίες τρέχουν πάνω στον ίδιο κώδικα, οπότε δεν υπάρχουν ξεχωριστές μεταβλητές ή δομές δεδομένων και πολλαπλά threads μπορεί παράλληλα να πειράζουν τις ίδιες δομές με αποτέλεσμα να υπάρχει πιο εύκολα η πιθανότητα τα έρθεις σε
deadlocks, race conditions, starvations κλπ κλπ. Το πλεονεκτημα τους είναι το μικρό overhead για το initialization (σε αντίθεση με τo fork νέων processes) αλλά και η ευκολία επικοινωνίας μεταξύ threads (αφού μοιράζονται το ίδιο memory space μπορεί μια δομή δεδομένων όπως ανέφερα παραπάνω να την πειράζουν περισσότερα απο ένα thread instances και συνεπώς να επικοινωνούν - γράφει κάτι το ένα thread ένα άλλο περιμένει και όταν το πρώτο το γράψει μπορεί να το διαβάσει κλπ κλπ). Στην περίπτωση επικοινωνίας μεταξύ processes, κάτι που αναφέρεται σαν
Inter-Process Communication (IPC) τα πράγματα δεν είναι τόσο απλά και για να επικοινωνήσουν δύο processes μέσα στο παιχνίδι μπαίνει το ίδιο το λειτουργικό (κάτι που επιφέρει τρομερό overhead σε σχέση με τα threads).
Zifnab wrote:
Υπάρχει τρόπος να φτιάξουμε processes στην java που να τρέχουν ψευδοταυτόχρονα?
Εδώ το έχασα λιγάκι. Όλα τα threads τρέχουν ψευδοπαράλληλα εκτός και εάν έχεις κάνει κάποιο lock και έχεις φτιάξει το δικό του scheduling μηχανισμό με αποτέλεσμα να ορίζεις εσύ ρητά ότι δεν θα τρέχουν παράλληλα.