Μεταβλητές υπό όρους γ. Μεταβλητές υπό όρους. Εφαρμογή. Βασικά στοιχεία του ActionScript

Για να μπορέσουμε να εφαρμόσουμε λογική στο πρόγραμμα, χρησιμοποιούνται εντολές υπό όρους. Θεωρητικά, αυτοί οι τελεστές μπορούν να αναπαρασταθούν ως κομβικά σημεία, με την επίτευξη των οποίων το πρόγραμμα επιλέγει σε ποια από τις πιθανές κατευθύνσεις θα προχωρήσει. Για παράδειγμα, θέλετε να προσδιορίσετε εάν κάποια μεταβλητή arg περιέχει θετικό ή αρνητικό αριθμό και να εμφανίσετε ένα αντίστοιχο μήνυμα στην οθόνη. Για να το κάνετε αυτό, μπορείτε να χρησιμοποιήσετε τη δήλωση if, η οποία εκτελεί παρόμοιους ελέγχους.

Στην απλούστερη περίπτωση, η σύνταξη αυτής της εντολής if είναι η εξής:

αν (έκφραση)

Εάν η τιμή της παραμέτρου έκφρασης είναι αληθής, η πρόταση εκτελείται, διαφορετικά παραλείπεται από το πρόγραμμα. Πρέπει να σημειωθεί ότι η "έκφραση" είναι μια έκφραση υπό όρους που ελέγχει κάποια συνθήκη. Στον πίνακα Το 2.1 παρουσιάζει επιλογές για απλές λογικές εκφράσεις του τελεστή if.

Πίνακας 2.1. Απλές εκφράσεις Boolean

Ακολουθεί ένα παράδειγμα χρήσης του τελεστή if branch. Το παρακάτω πρόγραμμα σάς επιτρέπει να προσδιορίσετε το πρόσημο της μεταβλητής που εισάγατε.

Λίστα 2.1. Το πρώτο πρόγραμμα για τον προσδιορισμό του πρόσημου του εισαγόμενου αριθμού.

#περιλαμβάνω
int main()
{
float x;
printf("Εισαγάγετε τον αριθμό: ");
scanf(“%f”,&x);
if(x >= 0)

Επιστροφή 0;
}

Η ανάλυση του παραπάνω κειμένου προγράμματος δείχνει ότι δύο προτάσεις υπό όρους μπορούν να αντικατασταθούν από μία χρησιμοποιώντας την κατασκευή

αν (έκφραση)

που ερμηνεύεται έτσι. Εάν η "έκφραση" είναι αληθής, τότε εκτελείται η "δήλωση1", διαφορετικά η "δήλωση2". Ας ξαναγράψουμε το προηγούμενο παράδειγμα προσδιορισμού του πρόσημου ενός αριθμού χρησιμοποιώντας αυτήν την κατασκευή.

Λίστα 2.2. Το δεύτερο πρόγραμμα για τον προσδιορισμό του πρόσημου του εισαγόμενου αριθμού.

#περιλαμβάνω
int main()
{
float x;
printf("Εισαγάγετε τον αριθμό: ");
scanf(“%f”,&x);
if(x printf("Ο εισαγόμενος αριθμός %f είναι αρνητικός.\n", x);
αλλού
printf("Ο εισαγόμενος αριθμός %f είναι μη αρνητικός.\n", x);

Επιστροφή 0;
}

Στα παραδείγματα που παρουσιάζονται, μετά τις εντολές if και else υπάρχει μόνο μία συνάρτηση printf(). Σε περιπτώσεις που, όταν πληρούται μια προϋπόθεση, είναι απαραίτητο να γραφτούν περισσότερες από μία δηλώσεις, είναι απαραίτητο να χρησιμοποιηθούν σγουρά σιδεράκια, π.χ. χρησιμοποιήστε μια κατασκευή όπως

αν (έκφραση)
{

}
αλλού
{

Θα πρέπει να σημειωθεί ότι μετά τη λέξη-κλειδί else, μπορείτε να τοποθετήσετε επίσημα μια άλλη πρόταση υπό όρους, η οποία θα οδηγήσει σε μια ακόμη πιο ευέλικτη κατασκευή πηδημάτων υπό όρους:

if (έκφραση 1)
else if (έκφραση 2)
αλλού

Η λίστα 2.3 δείχνει ένα πρόγραμμα που υλοποιεί την τελευταία κατασκευή άλματος υπό όρους.

Λίστα 2.3. Το τρίτο πρόγραμμα για τον προσδιορισμό του πρόσημου του εισαγόμενου αριθμού.

#περιλαμβάνω
int main()
{
float x;
printf("Εισαγάγετε τον αριθμό: ");
scanf(“%f”,&x);
if(x printf("Ο εισαγόμενος αριθμός %f είναι αρνητικός.\n", x);
αλλιώς if(x > 0)
printf("Ο εισαγόμενος αριθμός %f είναι θετικός.\n", x);
αλλού
printf("Ο εισαγόμενος αριθμός %f είναι μη αρνητικός.\n",x);

Επιστροφή 0;
}

Μέχρι στιγμής έχουμε εξετάσει απλές συνθήκες όπως x && - λογικές ΚΑΙ
|| - λογικό Ή
! – λογικό ΟΧΙ

Με βάση αυτές τις τρεις λογικές πράξεις, μπορούν να δημιουργηθούν πιο περίπλοκες συνθήκες. Για παράδειγμα, εάν υπάρχουν τρεις μεταβλητές exp1, exp2 και exp3, τότε μπορούν να σχηματίσουν τις λογικές δομές που παρουσιάζονται στον πίνακα. 2.2.

Πίνακας 2.2. Παράδειγμα σύνθετων λογικών εκφράσεων

Όπως οι πράξεις πολλαπλασιασμού και πρόσθεσης στα μαθηματικά, έτσι και οι λογικές πράξεις ΚΑΙ Ή ΟΧΙ έχουν επίσης τις δικές τους προτεραιότητες. Η λειτουργία ΟΧΙ έχει την υψηλότερη προτεραιότητα, δηλ. Αυτή η λειτουργία εκτελείται πρώτα. Η λειτουργία AND έχει τη χαμηλότερη προτεραιότητα και τέλος η λειτουργία OR έχει τη χαμηλότερη προτεραιότητα. Αυτές οι προτεραιότητες πρέπει να λαμβάνονται υπόψη κατά τον καθορισμό πολύπλοκων όρων. Για παράδειγμα, η συνθήκη

if(4 6 || 5 ελέγχεται με αυτόν τον τρόπο. Εάν 4 6 Ή 5 if(4 6 || 5 Ο τελεστής if υπό όρους διευκολύνει τη σύνταξη προγραμμάτων στα οποία πρέπει να επιλέξετε ανάμεσα σε έναν μικρό αριθμό πιθανών επιλογών. , μερικές φορές ένα πρόγραμμα χρειάζεται να επιλέξει μια επιλογή από πολλές πιθανές Επισήμως, μπορείτε να χρησιμοποιήσετε την κατασκευή if else για αυτό η γλώσσα C++ Η σύνταξη αυτού του τελεστή είναι η εξής:

διακόπτης (μεταβλητή)
{
σταθερά περίπτωσης1:

Περίπτωση σταθερά2:

...
Προκαθορισμένο:

Αυτός ο τελεστής ελέγχει διαδοχικά εάν η μεταβλητή είναι ίση με τις σταθερές που βρίσκονται μετά την περίπτωση της λέξης-κλειδιού. Εάν καμία από τις σταθερές δεν είναι ίση με την τιμή της μεταβλητής, τότε εκτελούνται οι δηλώσεις μετά τη λέξη προεπιλογή. Η δήλωση switch έχει την ακόλουθη δυνατότητα. Ας υποθέσουμε ότι η τιμή της μεταβλητής είναι ίση με την τιμή της σταθεράς1 και οι δηλώσεις μετά την πρώτη περίπτωση λέξης-κλειδιού εκτελούνται. Μετά από αυτό, η εκτέλεση του προγράμματος θα συνεχιστεί ελέγχοντας τη μεταβλητή για ισότητα με μια σταθερά2, η οποία συχνά οδηγεί σε αδικαιολόγητη σπατάλη πόρων υπολογιστή. Για να αποφύγετε αυτήν την κατάσταση, θα πρέπει να χρησιμοποιήσετε μια εντολή διακοπής για να μετακινήσετε το πρόγραμμα στην επόμενη πρόταση μετά την αλλαγή.

Η λίστα 2.4 δείχνει ένα παράδειγμα προγραμματισμού μιας δήλωσης μεταγωγής υπό όρους.

Λίστα 2.4. Ένα παράδειγμα χρήσης της εντολής switch.

#περιλαμβάνω
int main()
{
int x;
printf("Εισαγάγετε τον αριθμό: ");
scanf("%d",&x);
διακόπτης (x)
{
case 1: printf("Εισάγατε τον αριθμό 1\n");break;
περίπτωση 2: printf("Εισάγατε τον αριθμό 2\n"); Διακοπή;
προεπιλογή: printf("Εισάχθηκε άλλος αριθμός\n");
}
char ch;
printf("Εισαγάγετε χαρακτήρα: ");
scanf(“%c”,&ch);
διακόπτης (ch)
{
case ‘a’ : printf("Ο χαρακτήρας a\n έχει εισαχθεί"); Διακοπή;
case ‘b’ : printf("Ο χαρακτήρας b\n έχει εισαχθεί"); Διακοπή;
προεπιλογή: printf("Εισάχθηκε άλλος χαρακτήρας\n");
}
επιστροφή 0;
}

Αυτό το παράδειγμα δείχνει δύο διαφορετικές χρήσεις της εντολής switch. Στην πρώτη περίπτωση, αναλύεται το εισαγόμενο ψηφίο, στη δεύτερη περίπτωση, αναλύεται το εισαγόμενο σύμβολο. Θα πρέπει να σημειωθεί ότι αυτός ο τελεστής μπορεί να κάνει μια επιλογή μόνο με βάση την ισότητα του επιχειρήματός του με μία από τις αναφερόμενες τιμές περίπτωσης, δηλ. έλεγχος εκφράσεων όπως x

Μεταβλητές υπό όρους

Μια μεταβλητή συνθήκης (το condvar είναι συντομογραφία για τη μεταβλητή συνθήκης) χρησιμοποιείται για τον αποκλεισμό ενός νήματος με βάση κάποια συνθήκη κατά την εκτέλεση ενός κρίσιμου τμήματος κώδικα. Η συνθήκη μπορεί να είναι όσο σύνθετη επιθυμείτε και δεν εξαρτάται από τη μεταβλητή συνθήκης. Ωστόσο, μια μεταβλητή συνθήκης πρέπει πάντα να χρησιμοποιείται σε συνδυασμό με μια mutex για τον έλεγχο μιας συνθήκης.

Οι μεταβλητές υπό όρους υποστηρίζουν τις ακόλουθες συναρτήσεις:

· αναμονή για μια μεταβλητή υπό όρους (αναμονή) ( pthread_cond_wait());

· Ξεμπλοκάρισμα μιας ροής (σήμα) ( pthread_cond_signal())

· απεμπλοκή πολλαπλών ροών (μετάδοση) ( pthread_cond_broadcast()),

Ακολουθεί ένα παράδειγμα τυπικής χρήσης μιας μεταβλητής υπό όρους:

pthread_mutex_lock (&m) ;-…

ενώ (!αυθαίρετη συνθήκη) (

pthread_cond_wait(&cv, &m);

pthread_mutex_unlock (&m) ;

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

Ο βρόχος while στο παραπάνω παράδειγμα απαιτείται για δύο λόγους. Πρώτον, τα πρότυπα posix δεν εγγυώνται την απουσία ψευδών αφυπνίσεων (για παράδειγμα, σε συστήματα πολλαπλών επεξεργαστών). Δεύτερον, εάν ένα άλλο νήμα αλλάξει μια συνθήκη, πρέπει να ελεγχθεί ξανά για να διασφαλιστεί ότι η αλλαγή πληροί τα αποδεκτά κριτήρια. Όταν μπλοκάρεται ένα νήμα αναμονής, το mutex που σχετίζεται με τη μεταβλητή συνθήκης απελευθερώνεται ατομικά από τη συνάρτηση pthread_cond_wait()έτσι ώστε ένα άλλο νήμα να μπορεί να εισέλθει σε ένα κρίσιμο τμήμα του κώδικα προγράμματος.

Ένα νήμα που εκτελεί ένα μεμονωμένο νήμα κατάργηση αποκλεισμού ξεμπλοκάρει το νήμα υψηλότερης προτεραιότητας που βρίσκεται στην ουρά στη μεταβλητή συνθήκης. Η λειτουργία απεμπλοκής πολλαπλών νημάτων ξεμπλοκάρει όλα τα νήματα που βρίσκονται στην ουρά στη μεταβλητή συνθήκης. Το mutex που σχετίζεται με τη μεταβλητή συνθήκης απελευθερώνεται ατομικά από το νήμα με την υψηλότερη προτεραιότητα που ξεμπλοκάρεται. Μετά την επεξεργασία του κρίσιμου τμήματος του κώδικα, αυτό το νήμα πρέπει να απελευθερώσει το mutex.

Ένας άλλος τύπος λειτουργίας αναμονής μεταβλητής υπό όρους ( pthread__cond_timedwair()) σας επιτρέπει να ορίσετε ένα χρονικό όριο. Στο τέλος αυτής της περιόδου, το νήμα αναμονής μπορεί να ξεμπλοκάρει.

Εμπόδια

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

Σε αντίθεση με τη συνάρτηση pthreadjoin(), στο οποίο ένα νήμα περιμένει να ολοκληρωθεί ένα άλλο νήμα, το φράγμα αναγκάζει τα νήματα συναντώσε ένα ορισμένο σημείο. Μόλις ο καθορισμένος αριθμός νημάτων φτάσει στο διαμορφωμένο φράγμα, Ολααυτά τα νήματα θα ξεμπλοκαριστούν και θα συνεχίσουν τη δουλειά τους. Το φράγμα δημιουργείται χρησιμοποιώντας τη συνάρτηση pthread_barrier_init():

#περιλαμβάνω

pthread_barrier_init (pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count);

Αυτός ο κώδικας δημιουργεί ένα φράγμα στη δεδομένη διεύθυνση (ο δείκτης προς το φράγμα βρίσκεται στο όρισμα φραγμού) και με τα χαρακτηριστικά που ορίζονται από το όρισμα attr. Το όρισμα count καθορίζει τον αριθμό των νημάτων που πρέπει να καλούν pthread_barrier_wait().

Μετά τη δημιουργία του φραγμού, κάθε νήμα καλεί τη συνάρτηση pthread_barrier_wait(), σηματοδοτώντας έτσι την ολοκλήρωση αυτής της ενέργειας:

#περιλαμβάνω

int pthread_barrier_wait(pthread_barrier_t "barrier);

Όταν ένα νήμα καλεί μια συνάρτηση pthread_barrier_wait(),μπλοκάρει μέχρι τον αριθμό των νημάτων που καθορίζεται από τη συνάρτηση pthread_barrier_init(), δεν θα καλέσει τη συνάρτηση pthread_jbarrier_wait()και, κατά συνέπεια, δεν θα αποκλειστεί. Αφού ο καθορισμένος αριθμός νημάτων καλέσει τη συνάρτηση pthread_barrier_wait(), είναι όλα ξεκλείδωτα ΤΑΥΤΟΧΡΟΝΑ.

#περιλαμβάνω

#περιλαμβάνω

#περιλαμβάνω

#περιλαμβάνω

εμπόδιο pthread_barrier_t; // αντικείμενο συγχρονισμού τύπου "barrier".

main() // αγνοήστε ορίσματα

time_t now;// δημιουργήστε ένα φράγμα με τιμή μετρητή 3

pthread_barrier_init(&barrier, NULL, 3); // έναρξη δύο νημάτων - threadl και thread2

pthread_create(NOLL, NOLL, threadl, NULL); // Τα νήματα threadl και thread2 εκτελούνται

pthread_create(NDLL, NDLL, thread2, NDLL);//αναμονή για ολοκλήρωση

printf ("main() σε αναμονή για εμπόδιο στο %s", ctime (&τώρα));

pthread_barrier_wait (&barrier // μετά από αυτό το σημείο τερματίζονται και τα τρία νήματα).

printf ("φραγμός στο mainO έγινε στο %s", ctime (&τώρα));

threadl (κενό *δεν χρησιμοποιείται)

ώρα (&τώρα); // Εκτελέστε υπολογισμούς

printf ("νήμα που ξεκινά από %s", ctime (&τώρα));

pthread_barrier_wait (&barrier) ;// μετά από αυτό το σημείο και τα τρία νήματα τερματίζονται

printf ("barrier in threadl() που έγινε στο %s", ctime (&now)) ;

νήμα 2 (κενό *not__used)

ώρα (&τώρα); // Εκτελέστε υπολογισμούς

printf ("thread2 starting at %s", ctime (&now));

pthread_barrier_wait (&barrier) ;

// μετά από αυτό το σημείο ολοκληρώνονται και τα τρία νήματα

printf ("barrier in thread2() που έγινε στο %s", ctime (&τώρα));

Στο παράδειγμα από την καταχώριση, το κύριο νήμα δημιουργεί ένα φράγμα, μετά το οποίο αρχίζει να μετράει τον αριθμό των νημάτων που έχουν αποκλειστεί στο φράγμα για συγχρονισμό. Σε αυτήν την περίπτωση, ο αριθμός των συγχρονισμένων νημάτων ορίζεται σε 3: thread main(), thread thread1() και thread thread2().

Ξεκινούν τα νήματα thread1() και thread2(). Για λόγους σαφήνειας, τίθεται μια παύση στη ροή για την προσομοίωση της διαδικασίας υπολογισμού. Για να πραγματοποιηθεί ο συγχρονισμός, το κύριο νήμα μπλοκάρεται σε ένα φράγμα και περιμένει για ξεκλείδωμα, το οποίο θα συμβεί αφού τα άλλα δύο νήματα δεν το ενώσουν σε αυτό το φράγμα.



Αναμονή για αποκλεισμό

Οι κλειδαριές ύπνου λειτουργούν παρόμοια με τις μεταβλητές κατάστασης, με μερικές εξαιρέσεις. Όπως και οι υπό όρους μεταβλητές που περιμένουν ένα κλείδωμα ( pthread_sleepon_lock()) μπορεί να χρησιμοποιηθεί για τον αποκλεισμό ενός νήματος μέχρι να γίνει αληθής μια συνθήκη (παρόμοια με την αλλαγή της τιμής μιας θέσης μνήμης). Ωστόσο, σε αντίθεση με τις μεταβλητές συνθήκης (οι οποίες πρέπει να υπάρχουν για κάθε κατάσταση που ελέγχεται), τα κλείδωμα αναμονής ισχύουν για μια μεμονωμένη μεταβλητή συνθήκης mm.tex και δυναμικά δημιουργημένη, ανεξάρτητα από τον αριθμό των συνθηκών που ελέγχονται. Ο μέγιστος αριθμός μεταβλητών συνθήκης ισούται τελικά με τον μέγιστο αριθμό αποκλεισμένων νημάτων.

Μπορείτε να αποθηκεύσετε γνώσεις σχετικά με τους συνομιλητές σας ή οποιαδήποτε άλλη πληροφορία κειμένου. Τώρα, όταν γράφετε πρότυπα, μπορείτε να χρησιμοποιήσετε 13 μεταβλητές που έχουν προκαθορισμένο σκοπό και 100 «δωρεάν», τις οποίες οι κάτοχοι πληροφοριών μπορούν να χρησιμοποιήσουν κατά την κρίση τους.
Οι μεταβλητές με ένα δεδομένο σκοπό έχουν «ενδεικτικά» ονόματα. Για παράδειγμα, %user_nameείναι μια μεταβλητή που έχει σχεδιαστεί για να αποθηκεύει το όνομα του συνομιλητή. Το όνομά της χρησιμοποιεί τις αγγλικές λέξεις user ("user") και name ("name"). Τέτοιες μεταβλητές χρησιμοποιούνται ενεργά από τους προγραμματιστές κατά τη δημιουργία μιας βάσης δεδομένων τυπικών προτύπων πληροφοριών, βάσει των οποίων δημιουργούνται όλες οι πληροφορίες χρήστη στο έργο.
Η διάρκεια ζωής τέτοιων μεταβλητών δεν είναι περιορισμένη, δηλ. τα νοήματά τους απομνημονεύονται και αποθηκεύονται μεταξύ των μεμονωμένων συνομιλιών.

Τι αναγράφεται στα πρότυπα Παράδειγμα διαλόγου
Θυμηθείτε το όνομα:
$ Το όνομά μου είναι *
# Χαίρομαι που σε γνωρίζω. [%user_name="[*1]"]
Επισκέπτης:Με λένε Βάσια
Πληροφορίες:Μια φορά να σε γνωρίσω.
Εμφανίζουμε το όνομα του συνομιλητή στις πληροφορίες απάντησης:
$ Αντίο, σημ.
# Αντίο [%user_name]
Επισκέπτης:Αντίο, inf.
Πληροφορίες:Αντίο Βάσια.
Επιλέγουμε την απάντηση ανάλογα με την τιμή της μεταβλητής %user_name:
$ Θυμάσαι το όνομά μου;
# (Φυσικά. Είστε [%user_name].)
# (Όχι. Δεν μου είπες το όνομά σου.)
Επισκέπτης:Θυμάσαι το όνομά μου;
Πληροφορίες:Σίγουρα. Είσαι η Βάσια.
ή
Επισκέπτης:Θυμάσαι το όνομά μου;
Πληροφορίες:Οχι. Δεν μου είπες το όνομά σου.
Δεν θέλουμε πλέον να αποθηκεύουμε το όνομα του συνομιλητή, επομένως επαναφέρουμε τη μεταβλητή
$Είσαι ανόητος.
# Αυτό ήταν, δεν είμαι πια φίλος μαζί σου και ξέχασα το όνομά σου. [%user_name=""]
Επισκέπτης:Είσαι ανόητος.
Πληροφορίες:Αυτό ήταν, δεν είμαι πια φίλος μαζί σου και ξέχασα το όνομά σου.

Εκχώρηση τιμής σε μια μεταβλητή και εκκαθάριση της μεταβλητής

Μπορείτε να αντιστοιχίσετε μια τιμή σε μια μεταβλητή ή να την επαναφέρετε στο μηδέν στις απαντήσεις.

Σύνταξη:[%variable = "value"]
Η εντολή εκχώρησης μεταβλητής περιβάλλεται πάντα από αγκύλες, οι οποίες είναι χαρακτήρες υπηρεσίας εδώ. Η τιμή μιας μεταβλητής βρίσκεται πάντα σε εισαγωγικά.
Παραδείγματα εκχώρησης αξίας:
$ Χορεύω ροκ εν ρολ.
# Ζηλεύω. Οι inf δεν μπορούν να χορέψουν [%var1="dancing"]

$*μισώ*χορό*
$*χορός*μίσος*
$ *μην χορεύεις*
# Είναι κρίμα. Αν ήμουν άνθρωπος, σίγουρα θα χόρευα. [%var1="δεν του αρέσει ο χορός"]

$ Είμαι ** χρονών.
# Δροσερή ηλικία! [%user_age="[*1]"]

Παράδειγμα επαναφοράς μιας μεταβλητής:
$ Δεν θέλω να μιλήσετε για την ηλικία μου.
# Ό,τι πείτε [%user_age=""]

Εκχώρηση τιμής σε μια μεταβλητή χρησιμοποιώντας τη συνάρτηση set

Λειτουργία set("Argument1", "Argument2", "Argument3")αντικαθιστά το όρισμα2 και εκχωρεί την τιμή του στη μεταβλητή που καθορίζεται στο όρισμα1. Το Argument3 έχει ως προεπιλογή την κενή συμβολοσειρά. Εάν το καθορίσετε ως κάτι διαφορετικό από μια κενή συμβολοσειρά, τότε δεν θα αντικατασταθεί κανένα κείμενο στη θέση της συνάρτησης set και θα εκχωρηθεί μόνο η τιμή της μεταβλητής.

Για παράδειγμα,
$το όνομά μου είναι **
#Χαίρομαι που σε γνωρίζω, [@set("user_name", "[@ ("[*1]")]")]!

Επισκέπτης:με λένε Βάσια
Πληροφορίες:Χαίρομαι που σε γνώρισα Βάσια!

Ή:
$το όνομά μου είναι **
# Θα θυμάμαι το όνομά σου. [@set("user_name", "[@ ("[*1]")]", "1")]

$ * τι * είναι * το * όνομά μου *
# Είστε [%user_name].

Επισκέπτης:Με λένε Λένα
Πληροφορίες:Θα θυμάμαι το όνομά σου.
Επισκέπτης:Λοιπόν, πώς με λένε;
Πληροφορίες:Είσαι η Λένα.

Εμφάνιση της τιμής μιας μεταβλητής στην απόκριση infa

Προκειμένου οι πληροφορίες να «εκφράζουν» την τιμή μιας μεταβλητής στην απάντηση, πρέπει απλώς να γράψετε αυτήν τη μεταβλητή στην απάντηση.
Σύνταξη:[%μεταβλητός]
Απαιτούνται τετράγωνες αγκύλες.

Παράδειγμα:
$ Αντίο, ρομπότ!
# Αντίο, [%user_name]!

Μεταβλητές υπό όρους

Μεταβλητή υπό όρουςείναι ένας σηματοφόρος που χρησιμοποιείται για να σηματοδοτήσει ένα γεγονός που έχει συμβεί. Μία ή περισσότερες διεργασίες (ή νήματα) ενδέχεται να περιμένουν ένα σήμα ότι κάποιο συμβάν έχει συμβεί από άλλες διεργασίες ή νήματα. Θα πρέπει να κατανοήσετε τη διαφορά μεταξύ των μεταβλητών συνθήκης και των σηματοφόρων mutex που συζητήθηκαν παραπάνω. Ο σκοπός ενός σηματοφόρου mutex και των κλειδαριών ανάγνωσης-εγγραφής είναι ο συγχρονισμός της πρόσβασης στα δεδομένα, ενώ οι μεταβλητές συνθήκης χρησιμοποιούνται συνήθως για το συγχρονισμό μιας ακολουθίας λειτουργιών. Για το θέμα αυτό στο βιβλίο του Προγραμματισμός δικτύου UNIXΟ W. Richard Stevens το είπε καλά: « Τα Mutexe θα πρέπει να χρησιμοποιούνται για αποκλεισμό, όχι για αναμονή ».

Στη Λίστα 4.6, το νήμα καταναλωτή περιείχε έναν βρόχο:

15 while(TextFiles.empty())

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

Η μεταβλητή συνθήκης είναι του τύπου pthread_cond_t. Οι παρακάτω είναι οι τύποι λειτουργιών που μπορεί να εκτελέσει:

Αρχικοποίηση;

Καταστροφή;

Προσδοκία;

Αναμονή με χρονικό όριο.

Διευθυνσιοδοτούμενος συναγερμός;

Συναγερμός γενικής χρήσης;

Οι λειτουργίες αρχικοποίησης και καταστροφής εκτελούνται από μεταβλητές συνθήκης, παρόμοιες με παρόμοιες λειτουργίες άλλων mutexes. Λειτουργίες τάξης pthread_cond_t,που υλοποιούν αυτές τις λειτουργίες παρατίθενται στον πίνακα. 5.7.

Πίνακας 5.7. Συναρτήσεις της κλάσης pthread_cond_t που υλοποιούν πράξεις μεταβλητής υπό όρους

Οι μεταβλητές συνθήκης χρησιμοποιούνται σε συνδυασμό με mutexes. Εάν προσπαθήσετε να κλειδώσετε ένα mutex, το νήμα ή η διαδικασία θα αποκλειστεί μέχρι να απελευθερωθεί το mutex. Μόλις ξεμπλοκαριστεί, το νήμα ή η διαδικασία θα λάβει ένα mutex και θα συνεχίσει την εργασία του. Όταν χρησιμοποιείτε μια μεταβλητή συνθήκης, πρέπει να συσχετίζεται με μια mutex.

pthread_mutex_lock(&Mutex) ;

pthread_cond_wait(&EventMutex, &Mutex);

pthread_mutex_unlock(&Mutex) ;

Έτσι, κάποια εργασία προσπαθεί να κλειδώσει ένα mutex. Εάν το mutex είναι ήδη κλειδωμένο, τότε αυτή η εργασία είναι αποκλεισμένη. Μετά το ξεκλείδωμα, η εργασία θα απελευθερώσει το mutex Mutexκαι ταυτόχρονα θα περιμένει ένα σήμα για τη μεταβλητή υπό όρους EventMutex . Εάν το mutex δεν είναι κλειδωμένο, η εργασία θα περιμένει για ένα σήμα επ' αόριστον. Με μια χρονομετρημένη αναμονή, η εργασία θα περιμένει ένα σήμα για ένα καθορισμένο χρονικό διάστημα. Εάν ο χρόνος αυτός λήξει πριν λάβει σήμα η εργασία, η συνάρτηση θα επιστρέψει έναν κωδικό σφάλματος. Στη συνέχεια, η εργασία θα ζητήσει ξανά το mutex.

Εκτελώντας σηματοδότηση διεύθυνσης, μια εργασία ειδοποιεί ένα άλλο νήμα ή διαδικασία ότι έχει συμβεί κάποιο συμβάν. Εάν μια εργασία περιμένει ένα σήμα για μια δεδομένη μεταβλητή συνθήκης, αυτή η εργασία θα ξεμπλοκαριστεί και θα λάβει ένα mutex. Εάν πολλές εργασίες περιμένουν ένα σήμα για μια δεδομένη μεταβλητή υπό όρους ταυτόχρονα, τότε μόνο μία από αυτές θα ξεκλειδωθεί. Οι υπόλοιπες εργασίες θα περιμένουν στην ουρά και θα απελευθερωθούν σύμφωνα με τη στρατηγική προγραμματισμού που χρησιμοποιείται. Όταν εκτελείται μια λειτουργία καθολικής σηματοδότησης, θα ειδοποιηθούν όλες οι εργασίες που περιμένουν σήμα για την καθορισμένη μεταβλητή κατάστασης. Όταν ξεκλειδωθούν πολλές εργασίες, θα ανταγωνίζονται για την ιδιοκτησία του mutex σύμφωνα με τη στρατηγική προγραμματισμού που χρησιμοποιείται. Σε αντίθεση με μια λειτουργία αναμονής, μια εργασία που εκτελεί μια λειτουργία σηματοδότησης δεν διεκδικεί την ιδιοκτησία του mutex, αν και θα έπρεπε.

Η μεταβλητή υπό όρους έχει επίσης ένα αντικείμενο χαρακτηριστικών, οι συναρτήσεις του οποίου παρατίθενται στον πίνακα. 5.8.

Πίνακας 5.8. Λειτουργίες για την πρόσβαση σε ένα αντικείμενο χαρακτηριστικών για μια μεταβλητή συνθήκης τύπου pthread_cond_t


Int pthread_condattr_init(pthread_condattr_t * attr) Αρχικοποιεί το αντικείμενο χαρακτηριστικού της μεταβλητής συνθήκης που καθορίζεται από το attr στις προεπιλεγμένες τιμές για όλα τα χαρακτηριστικά που ορίζονται από την υλοποίηση.

Int pthread_condattr_destroy(pthread_condattr_t * attr) ; Καταστρέφει το αντικείμενο χαρακτηριστικού της μεταβλητής συνθήκης που καθορίζεται από την παράμετρο attr. Αυτό το αντικείμενο μπορεί να αρχικοποιηθεί εκ νέου καλώντας το pthread_condattr_init()

Int pthread_condattr_setpshared(pthread_condattr_t * attr,int pshared);

Int pthread_condattr_getpshared(const pthread_condattr_t * limited attr, int *restrict pshared); Ορίζει ή επιστρέφει το χαρακτηριστικό κοινής χρήσης διεργασίας του αντικειμένου χαρακτηριστικού της μεταβλητής συνθήκης που καθορίζεται από το attr. Η παράμετρος pshared μπορεί να περιέχει τις ακόλουθες τιμές:

PTHREAD_PROCESS_SHARED(επιτρέπει την κοινή χρήση κλειδώματος ανάγνωσης-εγγραφής από οποιαδήποτε νήματα που έχουν πρόσβαση στη μνήμη που έχει εκχωρηθεί σε αυτήν τη μεταβλητή συνθήκης, ακόμα κι αν τα νήματα ανήκουν σε διαφορετικές διεργασίες).

PTHREAD_PROCESS_PRIVATE(Η μεταβλητή συνθήκης μοιράζεται μεταξύ νημάτων της ίδιας διαδικασίας)

Int pthread_condattr_setclock(pthread_condattr_t * attr, clockid_t clock_id);

Int pthread_condattr_getclock(const pthread_condattr_t * περιορισμός attr, clockid_t * περιορισμός clock_id); Ορίζει ή επιστρέφει ένα χαρακτηριστικό ρολόιαντικείμενο χαρακτηριστικών μιας μεταβλητής υπό όρους που καθορίζεται από την παράμετρο attr. Χαρακτηριστικό ρολόιαντιπροσωπεύει το αναγνωριστικό του ρολογιού που χρησιμοποιείται για τη μέτρηση του χρονικού ορίου στη συνάρτηση pthread_cond_timedwait(). Το χαρακτηριστικό clock είναι προεπιλεγμένο στο αναγνωριστικό ρολογιού συστήματος

Μια μεταβλητή συνθήκης μπορεί να χρησιμοποιηθεί για την υλοποίηση των σχέσεων συγχρονισμού που αναφέρονται παραπάνω: start-start (CC), finish-start (FS), start-finish (SF) και finish-finish (FF). Αυτές οι σχέσεις μπορεί να υπάρχουν μεταξύ νημάτων της ίδιας ή διαφορετικών διεργασιών. Οι λίστες 5.4 και 5.5 παρέχουν παραδείγματα εφαρμογών σχέσεων συγχρονισμού FS και FF. Κάθε παράδειγμα ορίζει δύο mutexes. Το ένα mutex χρησιμοποιείται για το συγχρονισμό της πρόσβασης σε κοινόχρηστα δεδομένα και το άλλο χρησιμοποιείται για το συγχρονισμό της εκτέλεσης κώδικα.

// Λίστα 5.4. Σχέσεις συγχρονισμού FS μεταξύ

// δύο νήματα

pthread_t ThreadA,ThreadB;

pthread_cond_t Συμβάν;

άκυρο * εργάτης 1(κενό *X) (

for(int Count = l;Count

pthread_mutex_lock(&Mutex);

pthread_mutex_unlock(&Mutex);

if(Αριθμός == 50)(

pthread_cond_signal(&Event);

άκυρο * εργάτης2(κενό *X) (

pthread_mutex_lock(&EventMutex);

pthread_cond_wait(&Event,&EventMutex);

for(int Count = 1;Count

pthread_mutex_lock(&Mutex);

Αριθμός = Αριθμός + 20;

pthread_mutex_unlock(&Mutex);

cout ""Η συνάρτηση worker2 ολοκλήρωσε την εκτέλεση." "endl; επιστροφή(0);

ενθ κύριος(int argc, char *argv) (

pthread_mutex_init(&Mutex,NULL);

pthread_mutex_init(&EventMutex,NULL);

pthread_cond_init(&Event, NULL);

pthread_create(&ThreadA, NULL, workerl, NULL);

pthread_create(&ThreadB, NULL, worker2, NULL);

Η λίστα 5.4 δείχνει ένα παράδειγμα υλοποίησης σχέσεων συγχρονισμού FS. Το ThreadA δεν μπορεί να τερματιστεί μέχρι να ξεκινήσει το ThreadB. Εάν ο αριθμός γίνει 50, το ThreadA το σηματοδοτεί στο ThreadB. Τώρα μπορεί να συνεχίσει την εκτέλεση μέχρι το τέλος του ThreadB δεν μπορεί να ξεκινήσει την εκτέλεση μέχρι να λάβει ένα σήμα από το ThreadA. Το ThreadB χρησιμοποιεί ένα αντικείμενο EventMutex μαζί με μια μεταβλητή συνθήκης συμβάντος. Ένα αντικείμενο Mutex χρησιμοποιείται για τον συγχρονισμό της πρόσβασης για την εγγραφή της τιμής της κοινής μεταβλητής Number. Μια εργασία μπορεί να χρησιμοποιήσει πολλαπλά mutexe για να συγχρονίσει διάφορα συμβάντα και να αποκτήσει πρόσβαση σε κρίσιμες ενότητες.

Ένα παράδειγμα υλοποίησης σχέσεων συγχρονισμού FF παρουσιάζεται στην Λίστα 5.5.

// Λίστα 5.5. Σχέση συγχρονισμού FF μεταξύ // δύο νημάτων

pthread_t ThreadA, ThreadB ;

pthread_mutex_t Mutex, EventMutex;

pthread_cond_t Συμβάν;

void *workerl(void *X) (

for(int Count = l;Count

pthread_mu tex_l ock (&Mutex);

pthread_mutex_unlock(&Mutex);

cout ""workerl: αριθμός είναι "

pthread_mutex_lock(&EventMutex) ,-

cout "Η συνάρτηση workerl είναι σε αναμονή. " "endl;

pthread_cond_wait (&Event, &EventMutex) ;

pthread_mutex_unlock(&EventMutex);

void *worker2 (void *X) (

for(int Count = l;Count

pthread_mutex_lock(&Mutex) ;

Αριθμός = Αριθμός * 2 ;

pthread_mutex_unlock(&Mutex) ;

cout " "worker2: ο αριθμός είναι " "Αριθμός " endl;

pthread_cond_signal (&Event) ;

cout ""Η συνάρτηση worker2 έστειλε σήμα" "endl;

int main(int argc, char *argv) (

pthread_mutex_init (&Mutex,NULL) ;

pthread_mutex_init (&EventMutex,NULL) ;

pthread_cond_init (&Event, NULL) ;

pthread_create(&ThreadA, NULL,workerl, NULL);

pthread_create (&ThreadB, NULL, worker2, NULL) ;

Στη Λίστα 5.5, το ThreadA δεν μπορεί να τερματιστεί μέχρι να τερματιστεί το ThreadB. Το ThreadA πρέπει να ολοκληρώσει τον βρόχο 10 φορές και το ThreadB πρέπει να ολοκληρώσει τον βρόχο 100 φορές το ThreadA θα ολοκληρώσει τις επαναλήψεις του πριν από το ThreadB, αλλά θα περιμένει έως ότου το ThreadB σηματοδοτήσει την ολοκλήρωσή του.

Οι σχέσεις συγχρονισμού CC και SF δεν μπορούν να υλοποιηθούν με αυτόν τον τρόπο. Αυτές οι μέθοδοι χρησιμοποιούνται για το συγχρονισμό των πόρων Εγώχρόνος εκτέλεσης Εγώδιαδικασίες.



Έχετε ερωτήσεις;

Αναφέρετε ένα τυπογραφικό λάθος

Κείμενο που θα σταλεί στους συντάκτες μας: