τα στοιχεία επικοινωνίας μου
Ταχυδρομείο[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Thread: Μια οντότητα σε μια διαδικασία και η βασική μονάδα προγραμματισμού και αποστολής CPU. Το ίδιο το νήμα βασικά δεν κατέχει πόρους συστήματος, μόνο μερικούς πόρους που είναι απαραίτητοι για την εκτέλεση (όπως ένας μετρητής προγράμματος, ένα σύνολο καταχωρητών και μια στοίβα), αλλά μπορεί να μοιραστεί όλους τους πόρους που ανήκουν στη διαδικασία με άλλα νήματα που ανήκουν στην ίδια διαδικασία. Ένα νήμα μπορεί να δημιουργήσει και να καταστρέψει ένα άλλο νήμα στην ίδια διαδικασία μπορεί να εκτελεστεί ταυτόχρονα. Τα νήματα παρουσιάζουν διακοπτόμενη συμπεριφορά κατά τη λειτουργία. (Τα παραπάνω είναι από το "Εκμάθηση Επιπέδου 4 Υπολογιστή - Αρχές Λειτουργικού Συστήματος")
Όταν πρόκειται για νήματα, είναι απαραίτητο να μιλήσουμε για τον ορισμό της διαδικασίας: μια διεργασία είναι ένα πρόγραμμα με ορισμένες ανεξάρτητες λειτουργίες. (Τα παραπάνω είναι από το "Εκμάθηση Επιπέδου 4 Υπολογιστή - Αρχές Λειτουργικού Συστήματος")
Ο ορισμός της διαδικασίας είναι λίγο περίπλοκος Ας δούμε τι αποτελείται από μια διεργασία: πρόγραμμα, μπλοκ ελέγχου δεδομένων και διεργασίας. Μεταξύ αυτών, το πρόγραμμα αντιστοιχεί σε "ένα πρόγραμμα με ορισμένες ανεξάρτητες λειτουργίες" στον ορισμό της διαδικασίας. Ωστόσο, εκτός από το ίδιο το πρόγραμμα, η διαδικασία χρειάζεται επίσης δεδομένα (που μπορούν να γίνουν κατανοητά ως πόροι) και μπλοκ ελέγχου διεργασιών. Τα μπλοκ ελέγχου δεδομένων και διεργασιών είναι βασικοί πόροι όταν εκτελείται ένα πρόγραμμα Το πρόγραμμα βασίζεται σε αυτούς τους πόρους για την εκτέλεση αντίστοιχων δραστηριοτήτων, κάτι που ονομάζουμε "διαδικασία".
Δύο βασικές ιδιότητες των διεργασιών:
Μια διαδικασία είναι μια ανεξάρτητη μονάδα που μπορεί να κατέχει πόρους.
Μια διαδικασία είναι μια βασική μονάδα που μπορεί να προγραμματιστεί και να αποσταλεί ανεξάρτητα.
Όταν δημιουργήθηκαν για πρώτη φορά τα νήματα, ήταν να διαχωριστούν τα παραπάνω δύο χαρακτηριστικά της διεργασίας. Τα νήματα αποτελούν τη «βασική μονάδα προγραμματισμού και αποστολής της CPU». Μπορεί να πραγματοποιήσει παράλληλη εκτέλεση διεργασιών την ίδια στιγμή, τα νήματα κάτω από την ίδια διεργασία μπορούν να μοιράζονται όλους τους πόρους της διαδικασίας, οι οποίοι μπορούν να ικανοποιήσουν την πρόσβαση των πόρων διεργασίας από διαφορετικά νήματα κάτω από την ίδια διαδικασία. Η εμφάνιση νημάτων διαχωρίζει έξυπνα τα δύο χαρακτηριστικά της διαδικασίας, επιτρέποντας στη διαδικασία να χειριστεί καλύτερα τις ανάγκες παράλληλης εκτέλεσης.
Ένα νήμα είναι μια λειτουργία που εκτελείται. Τα νήματα POSIX είναι ένα σύνολο προτύπων, όχι ένα σύνολο υλοποιήσεων. Υπάρχουν και άλλα πρότυπα όπως: νήματα openmp.
Αναγνωριστικό νήματος: pthread_t (δεν ξέρω το συγκεκριμένο περιεχόμενο, κάθε εταιρεία το εφαρμόζει διαφορετικά, στο Linux είναι int)
Η εντολή px axm βλέπει διεργασίες και νήματα - που αντιπροσωπεύουν τα νήματα σε μια διεργασία. px ax -L για προβολή ελαφρών νημάτων.
int pthread_equal(pthread_t t1, pthread_t t2) Συγκρίνετε τους αριθμούς ID δύο νημάτων. Εάν είναι ίδιες, επιστρέφεται το μηδενικό εάν είναι διαφορετικά, επιστρέφεται το 0.
pthread_t pthread_self(void) Λάβετε το αναγνωριστικό νήματος του τρέχοντος νήματος
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
Ο προγραμματισμός νημάτων εξαρτάται από τη στρατηγική του προγραμματιστή.
- #include <stdlib.h>
- #include <stdio.h>
- #include <pthread.h>
- #include <string.h>
-
- void* myfunc(void *p)
- {
- puts("Thread is run!");
-
- printf("thread %ld n",pthread_self());
- return NULL;
- }
-
- int main()
- {
- puts("Begin!");
- pthread_t tid;
- int ret;
- ret = pthread_create(&tid,NULL,myfunc ,NULL);
- if(ret)
- {
- fprintf(stderr,"%s n",strerror(ret));
- exit(1);
- }
- printf("main %ld n",pthread_self());
-
-
-
- puts("End!");
- }
1. Το νήμα επιστρέφει από τη ρουτίνα εκκίνησης και η τιμή επιστροφής είναι ο κωδικός εξόδου του νήματος.
2. Τα νήματα μπορούν να ακυρωθούν από άλλα νήματα στην ίδια διαδικασία.
3. Το νήμα καλεί τη συνάρτηση pthread_exit(). void pthread_exit(void *retval);
int pthread_join(pthread_t νήμα, void **retval Είναι ισοδύναμο με την αναμονή της διαδικασίας και χρησιμοποιείται για τη συλλογή πτωμάτων).
- #include <stdlib.h>
- #include <stdio.h>
- #include <pthread.h>
- #include <string.h>
-
- void* myfunc(void *p)
- {
- puts("Thread is run!");
-
- pthread_exit(NULL);//线程专用清理函数。
- // return NULL;
- }
-
-
- int main()
- {
- puts("Begin!");
- pthread_t tid;
- int ret;
- ret = pthread_create(&tid,NULL,myfunc ,NULL);
- if(ret)
- {
- fprintf(stderr,"%s n",strerror(ret));
- exit(1);
- }
- pthread_join(tid,NULL); //收尸
-
- puts("End!");
- }
pthread_cleanup_push( //Iquivalent to atexit
pthread_cleanup_pop() //Ισοδύναμο με ενεργή ανάκτηση δεδομένων.
void pthread_cleanup_push(void (*routine)(void *), είναι η υλοποίηση της μακροεντολής, gcc -E για προβολή προεπεξεργασίας
void *arg);
void pthread_cleanup_pop(int execute //Επιλέξτε εάν θέλετε να καλέσετε).Πρέπει να εμφανίζεται σε ζεύγη, υλοποιείται με μακροεντολές
- #include <stdlib.h>
- #include <stdio.h>
- #include <pthread.h>
- #include <string.h>
-
-
- void cleanup_fun(void*p)
- {
- puts(p);
- }
-
- void* myfunc(void *p)
- {
- puts("Thread is run!");
-
- pthread_cleanup_push(cleanup_fun,"cleanup:1");
- pthread_cleanup_push(cleanup_fun,"cleanup:2");
- pthread_cleanup_push(cleanup_fun,"cleanup:3");
-
- puts("push over!");
-
-
-
- pthread_exit(NULL);//线程专用清理函数。
- // return NULL;
- pthread_cleanup_pop(1) //线程退出后,全部都会调用;
- pthread_cleanup_pop(0);
- pthread_cleanup_pop(1);
- }
-
-
- int main()
- {
- puts("Begin!");
- pthread_t tid;
- int ret;
- ret = pthread_create(&tid,NULL,myfunc ,NULL);
- if(ret)
- {
- fprintf(stderr,"%s n",strerror(ret));
- exit(1);
- }
- pthread_join(tid,NULL); //收尸
-
- puts("End!");
- }
Εάν το τρέχον νήμα θέλει να συλλέξει το πτώμα, πρέπει πρώτα να ακυρώσει (pthread_cancel) και μετά να συλλέξει το πτώμα (pthread_join).
Ακύρωση νήματος: int pthread_cancel(pthread_t νήμα);
Η ακύρωση έχει δύο καταστάσεις: επιτρέπεται και δεν επιτρέπεται.
Δεν επιτρέπεται η ακύρωση: η εκτέλεση κώδικα συνεχίζεται ανεπηρέαστη.
Η επιτρεπόμενη ακύρωση χωρίζεται σε: ασύγχρονη ακύρωση και καθυστερημένη ακύρωση (προεπιλογή) -> καθυστερημένη απόκριση μέχρι το σημείο ακύρωσης.
Σημείο ακύρωσης: Τα σημεία ακύρωσης που ορίζονται από το Posix είναι κλήσεις συστήματος που μπορεί να προκαλέσουν συμφόρηση.
pthread_setcancelstate: Μπορεί να οριστεί η κατάσταση ακύρωσης.
pthread_setcanceltype: Μπορείτε να ορίσετε τη μέθοδο ακύρωσης.
pthread_testcancel: Η συνάρτηση δεν κάνει τίποτα, απλώς ακυρώνει το σημείο.
Αποκόλληση νήματος: int pthread_detach(pthread_t νήμα);
Συνάρτηση μονής προετοιμασίας δυναμικής μονάδας: int pthread_once(pthread_once_t *once_control,
void (*init_routine)(void));
pthread_once_t Once_control = PTHREAD_ONCE_INIT;
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
- #define LEFT 30000000
- #define RIGHT 30000200
- #define THRNUM (RIGHT-LEFT+1)
-
- void* thr_prime(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =LEFT;i<=RIGHT;i++)
- {
- err= pthread_create(tid+(i-LEFT),NULL,thr_prime,&i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
-
- for(i=LEFT;i<=RIGHT;i++)
- {
- pthread_join(tid[i-LEFT],NULL);
- }
-
- return 0;
- }
-
- void* thr_prime(void*p)
- {
- int i,j,mark;
-
- i = *(int*)p;
-
- mark = 1;
- for(j=2;j<i/2;j++)
- {
- if(i%j ==0)
- {
- mark = 0;
- break;
- }
- }
- if(mark)
- printf("%d is a primer n",i);
- pthread_exit(NULL);
- return NULL;
- }
Θα υπάρχει ανταγωνισμός όταν εκτελεστεί ο παραπάνω κώδικας. Επειδή οι παράμετροι μεταβιβάζονται από τη διεύθυνση, τα δεδομένα πρέπει να ανακτηθούν από το * και δεν υπάρχει εγγύηση εάν το προηγούμενο νήμα έχει εκτελέσει τη λειτουργία.
αστάρι0.γ
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
- #define LEFT 30000000
- #define RIGHT 30000200
- #define THRNUM (RIGHT-LEFT+1)
-
- void* thr_prime(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =LEFT;i<=RIGHT;i++)
- {
- err= pthread_create(tid+(i-LEFT),NULL,thr_prime,(void *)i);
- // err= pthread_create(tid+(i-LEFT),NULL,thr_prime,&i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
-
- for(i=LEFT;i<=RIGHT;i++)
- {
- pthread_join(tid[i-LEFT],NULL);
- }
-
- return 0;
- }
-
- void* thr_prime(void*p)
- {
- int i,j,mark;
-
- i = (int)p;
- // i = *(int*)p;
-
- mark = 1;
- for(j=2;j<i/2;j++)
- {
- if(i%j ==0)
- {
- mark = 0;
- break;
- }
- }
- if(mark)
- printf("%d is a primer n",i);
- pthread_exit(NULL);
- return NULL;
- }
primer0_e.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
-
- #define LEFT 30000000
- #define RIGHT 30000200
- #define THRNUM (RIGHT-LEFT+1)
-
- struct thr_arg_st
- {
- int n;
- };
-
- void* thr_prime(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- struct thr_arg_st* p;
- void *ptr;
- for(i =LEFT;i<=RIGHT;i++)
- {
- p = malloc(sizeof(*p));
- if(p ==NULL)
- {
- perror("malloc");
- exit(1);
- }
- p->n = i;
- err= pthread_create(tid+(i-LEFT),NULL,thr_prime,p); // p就是结构体指针就是n的地址
- // err= pthread_create(tid+(i-LEFT),NULL,thr_prime,&i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- //free 不能在这里free,必须取走数据在free
- }
-
- for(i=LEFT;i<=RIGHT;i++)
- {
- pthread_join(tid[i-LEFT],&ptr);// 收尸并且接受返回参数。
- free(ptr);
-
- }
-
- return 0;
- }
-
- void* thr_prime(void*p)
- {
- int i,j,mark;
-
- i = ((struct thr_arg_st*)p)->n;
-
- mark = 1;
- for(j=2;j<i/2;j++)
- {
- if(i%j ==0)
- {
- mark = 0;
- break;
- }
- }
- if(mark)
- printf("%d is a primer n",i);
- pthread_exit(p); //返回值返回p
- return NULL;
- }
προσθήκη.γ
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
-
- #define FILENAME "/tmp/out"
- #define THRNUM (20)
-
- void* thr_add(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =0;i<=THRNUM;i++)
- {
- err= pthread_create(tid+(i),NULL,thr_add,NULL);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
-
- for(i=0;i<=THRNUM;i++)
- {
- pthread_join(tid[i],NULL);
- }
-
- return 0;
- }
-
- void* thr_add(void*p)
- {
- FILE*fp;
- char line_buf[1024];
- int len_size = 1024;
- fp = fopen(FILENAME,"r+");
-
- fgets(line_buf,len_size,fp);
-
- fseek(fp,0,SEEK_SET);
-
- fprintf(fp,"%d n",atoi(line_buf)+1);
-
- fclose(fp);
-
- pthread_exit(NULL);
-
- return NULL;
- }
Ο ανταγωνισμός και οι συγκρούσεις μπορεί να προκύψουν όταν είκοσι νήματα διαβάζουν και γράφουν δεδομένα σε ένα αρχείο ταυτόχρονα. Πριν γράψει ένα νήμα, ένα άλλο νήμα διαβάζει τα τελευταία δεδομένα.
- #include <stdlib.h>
- #include <stdio.h>
- #include <error.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <signal.h>
- #include <pthread.h>
-
- #include "mytbf.h"
-
- struct mytbf_st
- {
- int cps;
- int burst;
- int token;
- int pos;
- pthread_mutex_t mut;
- };
- static pthread_mutex_t mut_job = PTHREAD_MUTEX_INITIALIZER;
- static pthread_t tid_alrm;
- pthread_once_t init_once = PTHREAD_ONCE_INIT;
-
- static struct mytbf_st* job[MYTBF_MAX];
-
- typedef void (*sighandler_t)(int);
-
-
- static int get_free_pos_unlocked(void)
- {
- for(int i=0;i< MYTBF_MAX;i++)
- {
- if(job[i]==NULL)
- return i;
- }
- return -1;
- }
-
- static void* thr_alrm(void*p)
- {
- while(1)
- {
- pthread_mutex_lock(&mut_job);
- for(int i=0;i<MYTBF_MAX;i++)
- {
- if(job[i] != NULL)
- {
- pthread_mutex_lock(&job[i]->mut);
- job[i]->token += job[i]->cps;
- if(job[i]->token >job[i]->burst )
- {
- job[i]->token = job[i]->burst;
- }
- pthread_mutex_unlock(&job[i]->mut);
- }
- }
- pthread_mutex_unlock(&mut_job);
- sleep(1);
- }
- return NULL;
- }
-
- static void module_unload()
- {
- pthread_cancel(tid_alrm);
- pthread_join(tid_alrm,NULL);
- //只能一个人掉,二个人调用容易出差
- for(int i=0;i<MYTBF_MAX;i++)
- {
- if(job[i]!=NULL)
- {
- mytbf_destroy(job[i]);
- }
- }
- pthread_mutex_destroy(&mut_job);
-
- }
-
- static void module_load()
- {
- int err;
- err = pthread_create(&tid_alrm,NULL,thr_alrm,NULL);
- if(err)
- {
- fprintf(stderr,"create errorn");
- exit(1);
- }
- atexit(module_unload);
- }
-
- mytbf_t* mytbf_init(int cps ,int burst) //C语言中,void*可以赋值给任何类型的指针,任何类型的指针也都可以赋值给void*
- {
- struct mytbf_st*me;
- int pos;
- pthread_once(&init_once,module_load); //只初始化一次
- me = malloc(sizeof(*me));
- if(me == NULL)
- return NULL;
-
- me->cps = cps;
- me->burst = burst;
- me->token = 0;
-
- pthread_mutex_init(&me->mut,NULL);
-
- pthread_mutex_lock(&mut_job);
-
- pos = get_free_pos_unlocked();
- if(pos < 0)
- {
-
- pthread_mutex_unlock(&mut_job);
- free(me);
- return NULL;
- }
- me->pos = pos;
- job[pos] = me;
-
- pthread_mutex_unlock(&mut_job);
-
- return me;
-
- }
- int mytbf_fetchtoken(mytbf_t*ptr,int size) //获取token
- {
- if(size <= 0)
- return -EINVAL; //参数非法
- struct mytbf_st*me = ptr;
- pthread_mutex_lock(&me->mut);
- while(me->token <= 0 ) //token为空就等待
- {
- pthread_mutex_unlock(&me->mut);
- sched_yield();
- pthread_mutex_lock(&me->mut);
- }
-
- int n = (me->token>size?size:me->token);
- me->token -= n;
- pthread_mutex_unlock(&me->mut);
- return n;
- }
-
- int mytbf_returntoken(mytbf_t*ptr,int size) //返还token
- {
- if(size<=0)
- return -EINVAL;
- struct mytbf_st*me = ptr;
-
- pthread_mutex_lock(&me->mut);
-
- me->token+= size;
- if(me->token > me->burst)
- me->token = me->burst;
-
- pthread_mutex_unlock(&me->mut);
- return size;
- }
-
- int mytbf_destroy(mytbf_t*ptr)
- {
- struct mytbf_st *me;
- me = ptr;
- pthread_mutex_lock(&mut_job);
- job[me->pos] = NULL;
- pthread_mutex_unlock(&mut_job);
- pthread_mutex_destroy(&me->mut);
- free(ptr);
- return 0;
-
- }
Είναι ισοδύναμο με κλειδαριά και πρέπει να ξεκλειδωθεί για να μπορέσει να λειτουργήσει. (μέθοδος ερωτήματος)
Εάν ο man pthread_mutex_init αναφέρει ένα σφάλμα, εγκαταστήστε τις εξαρτήσεις:
sudo apt-get install manpages-posix manpages-posix-dev
int pthread_mutex_destroy(pthread_mutex_t *mutex)
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER
int pthread_mutex_lock(pthread_mutex_t *mutex); //加锁
int pthread_mutex_trylock(pthread_mutex_t *mutex);//Δοκιμάστε να κλειδώσετε, αν όχι, συνεχίστε την εκτέλεση
int pthread_mutex_unlock(pthread_mutex_t *mutex);//解锁
προσθήκη.γ
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
-
- #define FILENAME "/tmp/out"
- #define THRNUM (20)
-
- pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
-
- void* thr_add(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =0;i<THRNUM;i++)
- {
- err= pthread_create(tid+(i),NULL,thr_add,NULL);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
-
- for(i=0;i<THRNUM;i++)
- {
- pthread_join(tid[i],NULL);
- }
- pthread_mutex_destroy(&mut);
- return 0;
- }
-
- void* thr_add(void*p)
- {
- FILE*fp;
- char line_buf[1024];
- int len_size = 1024;
-
- pthread_mutex_lock(&mut);
-
-
- fp = fopen(FILENAME,"r+");
- fgets(line_buf,len_size,fp);
-
- fseek(fp,0,SEEK_SET);
-
- fprintf(fp,"%d n",atoi(line_buf)+1);
- fclose(fp);
- pthread_mutex_unlock(&mut);
-
- pthread_exit(NULL);
-
- return NULL;
- }
abcd.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
-
- #define FILENAME "/tmp/out"
- #define THRNUM (4)
-
- pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
-
- void* thr_abcd(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =0;i<THRNUM;i++)
- {
- err= pthread_create(tid+(i),NULL,thr_abcd,(void*)i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
- alarm(2);
-
- for(i=0;i<THRNUM;i++)
- {
- pthread_join(tid[i],NULL);
- }
- pthread_mutex_destroy(&mut);
- return 0;
- }
-
- void* thr_abcd(void*p)
- {
- int c = 'a'+ (int)p;
- while(1)
- {
- write(1,&c,1);
- }
-
- pthread_exit(NULL);
-
- return NULL;
- }
abcd.c
Χρησιμοποιήστε την αλυσίδα για να κλειδώσετε και να ξεκλειδώσετε.
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
-
- #define FILENAME "/tmp/out"
- #define THRNUM (4)
-
- pthread_mutex_t mut[THRNUM];
-
- void* thr_abcd(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =0;i<THRNUM;i++)
- {
- pthread_mutex_init(mut+i,NULL); //初始化四个锁
- pthread_mutex_lock(mut+i);
-
- err= pthread_create(tid+(i),NULL,thr_abcd,(void*)i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
- pthread_mutex_unlock(mut+0);
- alarm(2);
-
- for(i=0;i<THRNUM;i++)
- {
- pthread_join(tid[i],NULL);
- }
- pthread_mutex_destroy(&mut);
- return 0;
- }
- int next(int n)
- {
- if(n +1 ==THRNUM)
- return 0;
- return n+1;
- }
- void* thr_abcd(void*p)
- {
- int c = 'a'+ (int)p;
- int n = (int)p;
- while(1)
- {
- pthread_mutex_lock(mut+n);
- write(1,&c,1);
- pthread_mutex_unlock(mut+next(n) );
- }
- pthread_exit(NULL);
-
- return NULL;
- }
Ο αλγόριθμος συγκέντρωσης υλοποιεί τον υπολογισμό του πρώτου αριθμού (μέθοδος ερωτήματος)
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
- #define LEFT 30000000
- #define RIGHT 30000200
- #define THRNUM (RIGHT-LEFT+1)
-
- void* thr_prime(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =LEFT;i<=RIGHT;i++)
- {
- err= pthread_create(tid+(i-LEFT),NULL,thr_prime,(void *)i);
- // err= pthread_create(tid+(i-LEFT),NULL,thr_prime,&i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
-
- for(i=LEFT;i<=RIGHT;i++)
- {
- pthread_join(tid[i-LEFT],NULL);
- }
-
- return 0;
- }
-
- void* thr_prime(void*p)
- {
- int i,j,mark;
-
- i = (int)p;
- // i = *(int*)p;
-
- mark = 1;
- for(j=2;j<i/2;j++)
- {
- if(i%j ==0)
- {
- mark = 0;
- break;
- }
- }
- if(mark)
- printf("%d is a primer n",i);
- pthread_exit(NULL);
- return NULL;
- }
Νόμος ειδοποίησης για επικοινωνία.
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_init(pthread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr);
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);//Ξυπνήστε οποιαδήποτε αναμονή
int pthread_cond_timedwait(pthread_cond_t *restrict cond, //timeout wait
pthread_mutex_t *περιορισμός mutex,
const struct timespec *restrict abstime);
int pthread_cond_wait(pthread_cond_t *restrict cond, //死等
pthread_mutex_t *restrict mutex);
mytbf.c (μέθοδος ειδοποίησης)
- #include <stdlib.h>
- #include <stdio.h>
- #include <error.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <signal.h>
- #include <pthread.h>
-
- #include "mytbf.h"
-
- struct mytbf_st
- {
- int cps;
- int burst;
- int token;
- int pos;
- pthread_mutex_t mut;
- pthread_cond_t cond;
-
- };
- static pthread_mutex_t mut_job = PTHREAD_MUTEX_INITIALIZER;
- static pthread_t tid_alrm;
- pthread_once_t init_once = PTHREAD_ONCE_INIT;
-
- static struct mytbf_st* job[MYTBF_MAX];
-
- typedef void (*sighandler_t)(int);
-
-
- static int get_free_pos_unlocked(void)
- {
- for(int i=0;i< MYTBF_MAX;i++)
- {
- if(job[i]==NULL)
- return i;
- }
- return -1;
- }
-
- static void* thr_alrm(void*p)
- {
- while(1)
- {
- pthread_mutex_lock(&mut_job);
- for(int i=0;i<MYTBF_MAX;i++)
- {
- if(job[i] != NULL)
- {
- pthread_mutex_lock(&job[i]->mut);
- job[i]->token += job[i]->cps;
- if(job[i]->token >job[i]->burst )
- {
- job[i]->token = job[i]->burst;
- }
- pthread_cond_broadcast(&job[i]->cond);
- pthread_mutex_unlock(&job[i]->mut);
- }
- }
- pthread_mutex_unlock(&mut_job);
- sleep(1);
- }
- return NULL;
- }
-
- static void module_unload()
- {
- pthread_cancel(tid_alrm);
- pthread_join(tid_alrm,NULL);
- //只能一个人掉,二个人调用容易出差
- for(int i=0;i<MYTBF_MAX;i++)
- {
- if(job[i]!=NULL)
- {
- mytbf_destroy(job[i]);
- }
- }
- pthread_mutex_destroy(&mut_job);
-
- }
-
- static void module_load()
- {
- int err;
- err = pthread_create(&tid_alrm,NULL,thr_alrm,NULL);
- if(err)
- {
- fprintf(stderr,"create errorn");
- exit(1);
- }
- atexit(module_unload);
- }
-
- mytbf_t* mytbf_init(int cps ,int burst) //C语言中,void*可以赋值给任何类型的指针,任何类型的指针也都可以赋值给void*
- {
- struct mytbf_st*me;
- int pos;
- pthread_once(&init_once,module_load); //只初始化一次
- me = malloc(sizeof(*me));
- if(me == NULL)
- return NULL;
-
- me->cps = cps;
- me->burst = burst;
- me->token = 0;
-
- pthread_mutex_init(&me->mut,NULL);
- pthread_cond_init(&me->cond,NULL);
- pthread_mutex_lock(&mut_job);
-
- pos = get_free_pos_unlocked();
- if(pos < 0)
- {
-
- pthread_mutex_unlock(&mut_job);
- free(me);
- return NULL;
- }
- me->pos = pos;
- job[pos] = me;
-
- pthread_mutex_unlock(&mut_job);
-
- return me;
-
- }
- int mytbf_fetchtoken(mytbf_t*ptr,int size) //获取token
- {
- if(size <= 0)
- return -EINVAL; //参数非法
- struct mytbf_st*me = ptr;
- pthread_mutex_lock(&me->mut);
- while(me->token <= 0 ) //token为空就等待
- {
- pthread_cond_wait(&me->cond,&me->mut); //解锁等待,等待conad_broadcast和conad_signal的到来
-
- /*
- pthread_mutex_unlock(&me->mut);
- sched_yield();
- pthread_mutex_lock(&me->mut);
- */
- }
-
-
- int n = (me->token>size?size:me->token);
- me->token -= n;
- pthread_mutex_unlock(&me->mut);
- return n;
- }
-
- int mytbf_returntoken(mytbf_t*ptr,int size) //返还token
- {
- if(size<=0)
- return -EINVAL;
- struct mytbf_st*me = ptr;
-
- pthread_mutex_lock(&me->mut);
-
- me->token+= size;
- if(me->token > me->burst)
- me->token = me->burst;
- pthread_cond_broadcast(&me->cond);
- pthread_mutex_unlock(&me->mut);
- return size;
- }
-
- int mytbf_destroy(mytbf_t*ptr)
- {
- struct mytbf_st *me;
- me = ptr;
- pthread_mutex_lock(&mut_job);
- job[me->pos] = NULL;
- pthread_mutex_unlock(&mut_job);
- pthread_mutex_destroy(&me->mut);
- pthread_cond_destroy(&me->cond);
- free(ptr);
- return 0;
-
- }
primer0_pool.γ
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
- #include <sched.h>
-
- #define LEFT 30000000
- #define RIGHT 30000200
- #define THRNUM (4)
-
- static int num = 0;
- static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
- static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
-
- void* thr_prime(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
-
- for(i =0;i<=THRNUM;i++)
- {
- err= pthread_create(tid+(i),NULL,thr_prime,(void *)i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
- //下发任务
- for(i=LEFT;i<RIGHT;i++)
- {
- pthread_mutex_lock(&mut);
- while(num !=0) //不是0就需要等待任务被取走
- {
- pthread_cond_wait(&cond,&mut);
- }
-
- num = i; //下发任务
- pthread_cond_signal(&cond); //下游叫醒任意一个
- pthread_mutex_unlock(&mut);
- }
- pthread_mutex_lock(&mut);
- while(num!= 0)
- {
- pthread_mutex_unlock(&mut);
- sched_yield(); //出让调度器给别的线程
- }
- num = -1; //用于线程退出
- pthread_cond_broadcast(&cond);
-
- pthread_mutex_unlock(&mut);
-
- for(i=0;i<=THRNUM;i++)
- {
- pthread_join(tid[i],NULL);
- }
- pthread_mutex_destroy(&mut);
- pthread_cond_destroy(&cond);
- return 0;
- }
-
- void* thr_prime(void*p)
- {
- int i,j,mark;
- while(1)
- {
- pthread_mutex_lock(&mut);
- while(num == 0)
- {
- pthread_cond_wait(&cond,&mut);
- }
- if(num == -1)
- {
- pthread_mutex_unlock(&mut); //走到这里必须要解锁。
- break;
- }
-
- i= num;
- num = 0;
- pthread_cond_broadcast(&cond);
-
- pthread_mutex_unlock(&mut);
-
- mark = 1;
- for(j=2;j<i/2;j++)
- {
- if(i%j ==0)
- {
- mark = 0;
- break;
- }
- }
- if(mark)
- printf("[%d]%d is a primer n",(int)p,i);
- }
-
- pthread_exit(NULL);
- return NULL;
- }
abcd_cond.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
-
- #define FILENAME "/tmp/out"
- #define THRNUM (4)
-
- pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
- pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
- int num;
-
- void* thr_abcd(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =0;i<THRNUM;i++)
- {
-
- err= pthread_create(tid+(i),NULL,thr_abcd,(void*)i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
-
- alarm(2);
-
- for(i=0;i<THRNUM;i++)
- {
- pthread_join(tid[i],NULL);
- }
- pthread_cond_destroy(&cond);
- pthread_mutex_destroy(&mut);
- return 0;
- }
- int next(int n)
- {
- if(n +1 ==THRNUM)
- return 0;
- return n+1;
- }
- void* thr_abcd(void*p)
- {
- int c = 'a'+ (int)p;
- int n = (int)p;
- while(1)
- {
- pthread_mutex_lock(&mut);
- while(num != n)
- {
- pthread_cond_wait(&cond,&mut);
- }
- write(1,&c,1);
- num = next(num);
- pthread_cond_broadcast(&cond);
- pthread_mutex_unlock(&mut );
- }
- pthread_exit(NULL);
-
- return NULL;
- }
Το mutex είναι τύπου bool και ο σηματοφόρος είναι τύπου int Μειώνεται όταν χρησιμοποιείται.
mysem.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <pthread.h>
- #include <string.h>
- #include <unistd.h>
- #include "mysem.h"
-
- struct mysem_st
- {
- int value;
- pthread_mutex_t mut;
- pthread_cond_t cond;
-
- };
-
- mysem_t* mysem_init(int initval)
- {
- struct mysem_st*me;
- me = malloc(sizeof(*me));
- if(me==NULL)
- return NULL;
- me->value = initval;
- pthread_mutex_init(&me->mut,NULL);
- pthread_cond_init(&me->cond,NULL);
-
- return me;
-
- }
-
- int mysem_add(mysem_t*ptr ,int n)
- {
- struct mysem_st*me = ptr;
-
- pthread_mutex_lock(&me->mut);
-
- me->value+= n;
- pthread_cond_broadcast(&me->cond);
- pthread_mutex_unlock(&me->mut);
-
- return n;
- }
-
- int mysem_sub(mysem_t*ptr ,int n )
- {
- struct mysem_st*me = ptr;
-
- pthread_mutex_lock(&me->mut);
- while(me->value <n)
- {
- pthread_cond_wait(&me->cond,&me->mut);
- }
- me->value -=n;
-
- pthread_mutex_unlock(&me->mut);
- return n;
- }
-
- void mysem_destroy(mysem_t*ptr)
- {
- struct mysem_st*me = ptr;
- pthread_mutex_destroy(&me->mut);
- pthread_cond_destroy(&me->cond);
- free(me);
- }
-
-
-
mysem.h
- #ifndef MYSEM_H
- #define MYSEM_H
-
- typedef void mysem_t;
-
- mysem_t* mysem_init(int initval);
-
- int mysem_add(mysem_t*,int);
-
- int mysem_sub(mysem_t*,int);
-
- void mysem_destroy(mysem_t*);
-
-
-
- #endif
κύρια.γ
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
- #include "mysem.h"
-
- #define LEFT 30000000
- #define RIGHT 30000200
- #define THRNUM (RIGHT-LEFT+1)
-
- #define N 4
- static mysem_t* sem;
-
- void* thr_prime(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
-
- sem = mysem_init(N);
- if(sem ==NULL)
- {
- fprintf(stderr,"mysem_init n");
- exit(1);
- }
-
- for(i =LEFT;i<=RIGHT;i++)
- {
- mysem_sub(sem,1);
-
- err= pthread_create(tid+(i-LEFT),NULL,thr_prime,(void *)i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
-
- for(i=LEFT;i<=RIGHT;i++)
- {
- pthread_join(tid[i-LEFT],NULL);
- }
-
- mysem_destroy(sem);
-
- return 0;
- }
-
- void* thr_prime(void*p)
- {
- int i,j,mark;
-
- i = (int)p;
- // i = *(int*)p;
-
- mark = 1;
- for(j=2;j<i/2;j++)
- {
- if(i%j ==0)
- {
- mark = 0;
- break;
- }
- }
- if(mark)
- printf("%d is a primer n",i);
-
- sleep(5); //ps ax -L 可以观察到对线程进行了限制,只创建了四个线程
-
- mysem_add(sem,1);
- pthread_exit(NULL);
-
- return NULL;
- }
makefile
- all:mysem
- CFLAGS+=-g -Wall -pthread
- LDFLAGS+= -pthread
-
- mysem:main.o mysem.o
- gcc $^ $(CFLAGS) $(LDFLAGS) -o $@
-
- clean:
- rm -rf *.o mysem
Ολοκληρωμένη χρήση mutexes και σηματοφόρων. Χωρίζεται σε κλειδαριά ανάγνωσης (σηματοφορέας) και κλειδαριά εγγραφής (mutex). Γενικά, θα πρέπει να τεθεί ένα ανώτατο όριο για ανάγνωση και γραφή.
Είναι απαραίτητο να αποτρέψουμε τους συγγραφείς να πεθάνουν από την πείνα.
Η δεύτερη παράμετρος του pthread_create είναι το χαρακτηριστικό του νήματος.
int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);
Ο μέγιστος αριθμός νημάτων που δημιουργήθηκαν από το δοκιμαστικό πρόγραμμα. ()
- #include <stdlib.h>
- #include <stdio.h>
- #include <pthread.h>
-
- void* func(void)
- {
- int i;
-
- // printf("%pn",&i);
- pthread_exit(NULL);
- return NULL;
- }
-
- int main()
- {
- int err;
- pthread_t tid;
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setstacksize(&attr,1024*1024); //1mb
-
- int i = 0;
- for(;;i++)
- {
- err = pthread_create(&tid,&attr,func,NULL);
- if(err)
- {
- fprintf(stderr,"create errn");
- break;
- }
- }
- printf("max = %d n",i);
- pthread_attr_destroy(&attr);
- return 0;
- }
Ιδιότητες Mutex:
int pthread_mutexattr_init(pthread_mutexattr_t *attr);
Ανατρέξτε στο pthread_mutexattr_destroy().
int pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, //λειτουργεί σε όλες τις διεργασίες
int *pshared);
int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr,
int pshared);
//Δημιουργία θυγατρικής διαδικασίας που μπορεί να μοιράζεται τον πίνακα περιγραφής αρχείων Μπορείτε επίσης να επιλέξετε να μην τον κοινοποιήσετε. Δεν υπάρχει διάκριση μεταξύ διεργασιών και νημάτων στο Linux
int clone(int (*fn)(void *), void *stack, int flags, void *arg, ...
/* pid_t *parent_tid, void *tls, pid_t *child_tid */ );
int pthread_mutexattr_gettype(const pthread_mutexattr_t *restrict attr,
int *restrict type);
int pthread_mutexattr_settype(pthread_mutexattr_t *attr, τύπος int);
Ιδιότητες μεταβλητής συνθήκης:
int pthread_condattr_destroy(pthread_condattr_t *attr);
int pthread_condattr_init(pthread_condattr_t *attr);
Ιδιότητες κλειδώματος ανάγνωσης-εγγραφής:
Μια συνάρτηση επανεισαγωγής είναι απλώς μια συνάρτηση που μπορεί να διακοπεί, δηλαδή, μπορείτε να διακόψετε αυτή τη λειτουργία ανά πάσα στιγμή κατά την εκτέλεσή της και να τη μεταφέρετε στον προγραμματισμό του λειτουργικού συστήματος χωρίς σφάλματα κατά την επιστροφή του στοιχείου ελέγχου Οι συναρτήσεις χρησιμοποιούν ορισμένους πόρους του συστήματος, όπως καθολικές μεταβλητές περιοχές, πίνακες διανυσμάτων διακοπής, κ.λπ., επομένως, εάν διακοπούν, ενδέχεται να προκύψουν προβλήματα τέτοιες συναρτήσεις σε περιβάλλον πολλαπλών εργασιών.
IO σε multithreading. Η ξεκλείδωτη συνάρτηση τελειώνει με (συνάρτηση χωρίς επανεισαγωγή, η ταυτόχρονη πολλαπλών νημάτων δεν υποστηρίζεται). man putc_unlocked, προβολή μη υποστηριζόμενων λειτουργιών IO.
int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);
int sigwait(const sigset_t *set, int *sig);
int pthread_kill(pthread_t νήμα, int sig);
Ανατρέξτε στον επίσημο ιστότοπο: www.OpenMp.org
Οι συντακτικές ετικέτες Openmp υποστηρίζονται μετά το gcc4.0.Πόσες ταυτότητες μπορούν να επιτευχθούν με λίγες μόνο CPU;
γεια.γ
- #include <stdio.h>
- #include <stdlib.h>
-
- int main()
- {
- #pragma omp parallel //实现并发
- {
- puts("Hello ");
- puts(" World");
- }
- return 0;
- }
makefile
CFLAGS += -Wall -fopenmp
Compile make hello και εκτελέστε το.
- #include <stdio.h>
- #include <stdlib.h>
- #include <omp.h>
-
- int main()
- {
- #pragma omp parallel sections
- {
- #pragma omp section
- printf("[%d:]Hello n",omp_get_thread_num() );
- #pragma omp section
- printf("[%d:]World n",omp_get_thread_num() );
- }
- return 0;
- }