互斥锁
多任务下载示例:
#include <pthread.h>#include <stdio.h>#include <stdlib.h>#define NUM_OF_TASKS 5void *downloadfile(void *filename){printf("I am downloading the file %s!\n", (char *)filename);sleep(10);long downloadtime = rand()%100;printf("I finish downloading the file within %d minutes!\n", downloadtime);pthread_exit((void *)downloadtime);}int main(int argc, char *argv[]){char files[NUM_OF_TASKS][20]={"file1.avi","file2.rmvb","file3.mp4","file4.wmv","file5.flv"};pthread_t threads[NUM_OF_TASKS];int rc;int t;int downloadtime;pthread_attr_t thread_attr;pthread_attr_init(&thread_attr);pthread_attr_setdetachstate(&thread_attr,PTHREAD_CREATE_JOINABLE);for(t=0;t<NUM_OF_TASKS;t++){printf("creating thread %d, please help me to download %s\n", t, files[t]);rc = pthread_create(&threads[t], &thread_attr, downloadfile, (void *)files[t]);if (rc){printf("ERROR; return code from pthread_create() is %d\n", rc);exit(-1);}}pthread_attr_destroy(&thread_attr);for(t=0;t<NUM_OF_TASKS;t++){pthread_join(threads[t],(void**)&downloadtime);printf("Thread %d downloads the file %s in %d minutes.\n",t,files[t],downloadtime);}pthread_exit(NULL);}
一个运行中的线程可以调用 pthread_exit 退出线程。这个函数可以传入一个参数转换为(void *) 类型。这是线程退出的返回值。
接下来,我们来看主线程。在这里面,我列了五个文件名。接下来声明了一个数组,里面有五个 pthread_t 类型的线程对象。
接下来,声明一个线程属性 pthread_attr_t。我们通过 pthread_attr_init 初始化这个属性,并且设置属性 PTHREAD_CREATE_JOINABLE。这表示将来主线程程等待这个线程的结束,并获取退出时的状态。
接下来是一个循环。对于每一个文件和每一个线程,可以调用 pthread_create 创建线程。一共有四个参数,第一个参数是线程对象,第二个参数是线程的属性,第三个参数是线程运行函数,第四个参数是线程运行函数的参数。主线程就是通过第四个参数,将自己的任务派给子线程。
任务分配完毕,每个线程下载一个文件,接下来主线程要做的事情就是等待这些子任务完成。当一个线程退出的时候,就会发送信号给其他所有同进程的线程。有一个线程使用 pthread_join 获取这个线程退出的返回值。线程的返回值通过 pthread_join 传给主线程,这样子线程就将自己下载文件所耗费的时间,告诉给主线程。
好了,程序写完了,开始编译。多线程程序要依赖于 libpthread.so。
gcc download.c -lpthread
条件变量
#include <pthread.h>#include <stdio.h>#include <stdlib.h>#define NUM_OF_TASKS 3#define MAX_TASK_QUEUE 11char tasklist[MAX_TASK_QUEUE]="ABCDEFGHIJ";int head = 0;int tail = 0;int quit = 0;pthread_mutex_t g_task_lock;pthread_cond_t g_task_cv;void *coder(void *notused){pthread_t tid = pthread_self();while(!quit){pthread_mutex_lock(&g_task_lock);while(tail == head){if(quit){pthread_mutex_unlock(&g_task_lock);pthread_exit((void *)0);}printf("No task now! Thread %u is waiting!\n", (unsigned int)tid);pthread_cond_wait(&g_task_cv, &g_task_lock);printf("Have task now! Thread %u is grabing the task !\n", (unsigned int)tid);}char task = tasklist[head++];pthread_mutex_unlock(&g_task_lock);printf("Thread %u has a task %c now!\n", (unsigned int)tid, task);sleep(5);printf("Thread %u finish the task %c!\n", (unsigned int)tid, task);}pthread_exit((void *)0);}int main(int argc, char *argv[]){pthread_t threads[NUM_OF_TASKS];int rc;int t;pthread_mutex_init(&g_task_lock, NULL);pthread_cond_init(&g_task_cv, NULL);for(t=0;t<NUM_OF_TASKS;t++){rc = pthread_create(&threads[t], NULL, coder, NULL);if (rc){printf("ERROR; return code from pthread_create() is %d\n", rc);exit(-1);}}sleep(5);for(t=1;t<=4;t++){pthread_mutex_lock(&g_task_lock);tail+=t;printf("I am Boss, I assigned %d tasks, I notify all coders!\n", t);pthread_cond_broadcast(&g_task_cv);pthread_mutex_unlock(&g_task_lock);sleep(20);}pthread_mutex_lock(&g_task_lock);quit = 1;pthread_cond_broadcast(&g_task_cv);pthread_mutex_unlock(&g_task_lock);pthread_mutex_destroy(&g_task_lock);pthread_cond_destroy(&g_task_cv);pthread_exit(NULL);}

