一个程序可以包含多个进程,而一个进程又可以创建多个线程,每个线程都共享此进程的上下文环境。
在unix下使用gcc编译带有线程操作的程序时需要加上 -pthread选项。
基本的线程函数:
#include <<a target=_blank href="http://linux.die.net/include/pthread.h" rel="nofollow" style="color: rgb(102, 0, 0); text-decoration: none;"><span class="highlight" style="background-color: rgb(255, 204, 204);">pthread</span>.h</a>>
创建线程:后两个参数为待调用的函数及传递的参数
<strong>int pthread_create(pthread_t *</strong><em>thread</em><strong>, const pthread_attr_t *</strong><em>attr</em><strong>, void *(*</strong><em>start_routine</em><strong>) (void *), void *</strong><em>arg</em><strong>);</strong>在进程中等待相应线程的结束:
int pthread_join(pthread_t thread, void **retval);
1,创建一个能实现两数相加的线程,使用3个线程实现(a + b) * (c + d)/(e + f)。为此,我们使用一个结构体传递加数及结果:
typedef struct _Calcul { float op1, op2, result; } Calcul;
- #include<stdio.h>
- #include<stdlib.h>
- #include<unistd.h>
- #include<pthread.h>
- typedef struct _Calcul{ float op1, op2, result;}Calcul;
- void somme(Calcul* calcul)
- {
- calcul->result = calcul->op1 + calcul->op2;
- }
- void main()
- {
- int val_return;
- int **res1, res2, res3;
- pthread_t ptr1, ptr2, ptr3;
- Calcul calcul1, calcul2, calcul3;
- calcul1.op1=1;
- calcul1.op2=2;
- calcul2.op1=3;
- calcul2.op2=4;
- calcul3.op1=5;
- calcul3.op2=16;
- if( (val_return=pthread_create(&ptr1, NULL, (void*)somme, (void*)(&calcul1) )) != 0)
- {
- perror("pthread_create");exit(1);
- }
- if( (val_return=pthread_create(&ptr2, NULL, (void*)somme, (void*)(&calcul2) )) != 0)
- {
- perror("pthread_create");exit(1);
- }
- if( (val_return=pthread_create(&ptr3, NULL, (void*)somme, (void*)(&calcul3) )) != 0)
- {
- perror("pthread_create");exit(1);
- }
- pthread_join( ptr1, NULL);//(void**)res1);
- pthread_join( ptr2, NULL);//(void**)res1);
- pthread_join( ptr3, NULL);//(void**)res1);
- printf("(1+2)*(3+4)/(5+16)=%f\n", calcul1.result * calcul2.result / calcul3.result);
- }
2,使用互斥(mutex)实现对共享资源的访问,涉及到的函数有:
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
关于互斥,在这里就不详解了。总之如果有多个线程想要访问同一个资源(比如文件)的话,那么每个线程在访问共享资源之前都应该调用pthread_mutex_lock,成功返回后就好比给共享资源加了一把锁,其他的线程在调用这个函数时会被卡住,直到此进程将资源解锁:pthread_mutex_unlock。当然init和destroy分别用于在使用前初始化和用完摧毁这一互斥。
- #include<stdio.h>
- #include<stdlib.h>
- #include<errno.h>
- #include<unistd.h>
- #include<pthread.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- void ecrire( pthread_mutex_t * mutex)
- {
- FILE* fd;
- while(1)
- {
- pthread_mutex_lock(mutex);//c'est préférable de mettre les opération dans le corps de mutex
- //fd = open("verrou.txt", O_WRONLY | O_CREAT);
- fd = fopen("verrou.txt", "w");
- if( fd==NULL ){perror("open");exit(errno);}
- fputs("Je suis la fonction ecrire!", fd);
- printf("Pthread ecrire : vient d'écrire une phrase...\n");
- fclose(fd);
- pthread_mutex_unlock(mutex);
- sleep(10);
- }
- }
- void lire( pthread_mutex_t * mutex)
- {
- FILE* fd;
- char msg[50];
- while(1)
- {
- pthread_mutex_lock(mutex);
- fd = fopen("verrou.txt", "r");
- if( fd==NULL ){perror("open");exit(errno);}
- fgets( msg, 49, fd);
- fclose(fd);
- pthread_mutex_unlock(mutex);
- printf("Pthread lire : %s\n", msg);
- sleep(5);
- }
- }
- pthread_mutex_t mutex;
- void main()
- {
- int val_return;
- pthread_t ptr1, ptr2;
- pthread_mutex_init(&mutex, NULL);
- //mutex = PTHREAD_MUTEX_INITIALIZER;
- if( (val_return=pthread_create(&ptr1, NULL, (void*)ecrire, (void*)(&mutex) )) != 0)
- {
- perror("pthread_create");exit(1);
- }
- if( (val_return=pthread_create(&ptr2, NULL, (void*)lire, (void*)(&mutex) )) != 0)
- {
- perror("pthread_create");exit(1);
- }
- pthread_join( ptr1, NULL);//Si le proc termine, les threads sont aussi terminés
- pthread_join( ptr2, NULL);//(void**)res1);
- }
3,线程间的同步:barrier。
有这样一系列barrier函数可以在线程内部实现线程间的同步:
pthread_barrier_t barrier;
pthread_barrier_init(&barrier, NULL, THREAD_NUM);// Init the barrier with a number.
pthread_barrier_wait(&barrier);//The calling thread can continue only if there are THREAD_NUM threads who call this method.
pthread_barrier_destroy(&barrier);
简单地说,假如我们设置一个代表3个线程的barrier,并在3个线程中分别调用pthread_barrier_wait,那么只有当3个进程全部都执行到调用此函数的那行时,这3个线程才能继续向下进行。当第3个线程还没有到达此处时,前两个调用wait的线程都会被卡在那里,等待。
- /*
- The barrier is a way to synchronise threads during their executions,
- while pthread_join(), which is called in the body of the process,
- only synchronize the end of threads.
- pthread_barrier_t barrier;
- pthread_barrier_init(&barrier, NULL, THREAD_NUM);// Init the barrier with a number.
- pthread_barrier_wait(&barrier);//The calling thread can continue only if there are
- THREAD_NUM threads who call this method.
- pthread_barrier_destroy(&barrier);
- */
- #include<stdio.h>
- #include<stdlib.h>
- #include<errno.h>
- #include<unistd.h>
- #include<pthread.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #define THREAD_NUM 5
- pthread_barrier_t barrier;
- void travailler( )
- {
- int duree = ((int)random())%5+1;
- int threadid=pthread_self();
- printf("Pthread %d a une tâche de %d seconds.\n", threadid, duree);
- int i = 0;
- for(;i<duree;i++)
- {
- //If we put wait here, when a thread terminates, all others will be
- //suspended, because there will nerver be enough threads who call wait()
- //pthread_barrier_wait(&barrier);
- printf("Pthread %d, second %d.\n", threadid, i);
- sleep(1);
- }
- pthread_barrier_wait(&barrier);
- printf("Pthread %d termine.\n", threadid);
- }
- void main()
- {
- int val_return;
- pthread_t ptrs[THREAD_NUM];
- pthread_barrier_init(&barrier, NULL, THREAD_NUM);
- int i = 0;
- for(;i<THREAD_NUM;i++)
- {
- if( (val_return=pthread_create(ptrs+i, NULL, (void*)travailler, NULL)) != 0)
- {
- perror("pthread_create");exit(1);
- }
- }
- for(i=0;i<THREAD_NUM;i++)
- {
- pthread_join( ptrs[i], NULL);//Si le proc termine, les threads sont aussi terminés
- printf("Join thread %d .\n", i);
- }
- //pthread_barrier_destroy(&barrier);
- }